<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\ApiController;
use App\Http\Requests\SalePaymentUpdateRequest;
use App\Http\Requests\SaleStoreRequest;
use App\Http\Requests\SaleUpdateRequest;
use App\Http\Resources\PaymentMethodResource;
use App\Http\Resources\PosServiceTableResource;
use App\Http\Resources\PosStaffResource;
use App\Http\Resources\SaleDetailResource;
use App\Http\Resources\SaleResource;
use App\Models\FoodItem;
use App\Models\FoodItemAttribute;
use App\Models\Sale;
use App\Models\SaleItem;
use App\Models\ServiceTable;
use App\Notifications\App\OnCollectionNotification;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

class SaleController extends ApiController
{
    /**
     * Construct middleware
     */
    public function __construct()
    {
        $this->middleware('auth:sanctum');
    }

    public function index(Request $request): JsonResponse
    {
        $sort = $this->sort($request);
        $sales = Sale::filter($request->all())
            ->orderBy($sort['column'], $sort['order'])
            ->paginate((int) $request->get('perPage', 10));

        return response()->json(
            [
                'items' => SaleResource::collection($sales->items()),
                'pagination' => $this->pagination($sales),
            ]
        );
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */

    public function store(SaleStoreRequest $request)
    {
        DB::beginTransaction();
        try {
            $validated = $this->handleRequestWithOrderType($request);
            // Set default values for optional fields
            $validated['order_taker_id'] = $validated['order_taker_id'] ?? auth()->user()->id;
            $validated['took_at'] = $validated['took_at'] ?? now()->toDateTimeString();
            $validated['uuid'] = Str::orderedUuid();
            $validated['tracking'] = $this->getTrackingIdentity();

            if (config('app.modes.cashbooks')) {
                $validated['cash_book_id'] = $this->getActiveRegisterIdentity();
            }

            // Check if the table is being served for non-split dining orders
            if (!$validated['is_spliting'] && 'dining' === $validated['order_type'] && $this->checkTableIsServing($validated)) {
                return response()->json([
                    'message' => __('Attention! Table is being served'),
                ], 422);
            }

            // Create the Sale record
            $sale = Sale::create($validated);
            $this->createSaleItemRecords($sale, $validated['items']);

            // Update the table status for dining orders
            if ('dining' === $validated['order_type']) {
                $sale->serviceTable()->update(['is_booked' => true]);
            }
            if (!$validated['is_spliting']) {
                $sale->customer->notify((new OnCollectionNotification($this->channelConfigs($sale->customer), $sale))
                    ->locale(config('app.locale')));
            }
            \App\Helpers\ActivityLogger::log(__('New sale order created successfully'), $sale->tracking);
            DB::commit();
            return response()->json([
                'message' => __('Operation completed successfully'),
                'order' => $sale->uuid,
            ]);
        } catch (Exception $e) {
            DB::rollback();
            return response()->json(
                [
                    'error' => __('Something went wrong try again !'),
                    'message' => $e->getMessage(),
                ],
                422
            );
        }
    }

    /**
     * Display the specified resource.
     *
     * @param      \App\Models\Sale  $sale   The sale
     *
     * @return     JsonResponse      The json response.
     */
    public function show(Sale $sale): JsonResponse
    {
        return response()->json(new SaleDetailResource($sale));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Sale  $sale
     * @return \Illuminate\Http\Response
     */
    public function update(SaleUpdateRequest $request, Sale $sale)
    {
        $validated = $this->handleRequestWithOrderType($request);
        if ($validated['progress'] < 99) {
            $validated['prepared_at'] = null;
        }

        $isDiningOrder = 'dining' == $validated['order_type'];

        //checking table availibiltity
        if ($sale->serviceTable && $isDiningOrder && $validated['table_id'] !== $sale->serviceTable->id && $this->checkTableIsServing($validated)) {
            return response()->json([
                'message' => __('Attention! Table is being served'),
            ], 422);
        }
        //Making sure if service table is serving before changing order type.should be released.
        if ($sale->serviceTable) {
            $sale->serviceTable()->update(['is_booked' => false]);
        }

        $sale->update($validated);
        $sale->saleItems()->delete();
        $this->createSaleItemRecords($sale, $validated['items']);

        // Attach service table only of order type is dinning.
        if ($isDiningOrder) {
            $sale->serviceTable()->update(['is_booked' => true]);
        }

        \App\Helpers\ActivityLogger::log(__('Sale order updated successfully'), $sale->tracking);
        return response()->json([
            'message' => __('Order updated successfully'),
        ]);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\Sale  $sale
     * @return \Illuminate\Http\Response
     */
    public function destroy(Sale $sale): JsonResponse
    {
        if (!Auth::user()->userRole->checkPermission('remove_sales')) {
            return response()->json([
                'message' => __('You have not permit to perform this request'),
            ], 403);
        }
        if ('dining' === $sale->order_type) {
            $sale->serviceTable()->update(['is_booked' => false]);
        }
        \App\Helpers\ActivityLogger::log(__('Sale order removed successfully'), $sale->tracking);
        $sale->delete();
        return response()->json(['message' => __('Data removed successfully')]);
    }

    public function checkTableIsServing($validated): Bool
    {
        $table = ServiceTable::where('is_booked', true)->where('id', $validated['table_id'])->first();
        return $table ? true : false;
    }

    public function filters(): JsonResponse
    {
        return response()->json([
            'tables' => PosServiceTableResource::collection(ServiceTable::get()),
            'billers' => PosStaffResource::collection($this->getBillers()),
            'takers' => PosStaffResource::collection($this->getOrderTakers()),
            'chefs' => PosStaffResource::collection($this->getChefs()),
            'methods' => PaymentMethodResource::collection($this->paymentMethods()),
        ]);
    }

    protected function createSaleItemRecords(Sale $sale, $items)
    {
        foreach ($items as $item) {
            if ($item['food_item_id']) { // If it's a variant
                $attribute = FoodItemAttribute::findOrFail($item['id']);
                $product = FoodItem::findOrFail($item['food_item_id']);
                SaleItem::create([
                    'sale_id' => $sale->id,
                    'item_data' => $attribute,
                    'item_name' => $item['name'],
                    'quantity' => $item['qty'],
                    'price' => $item['price'],
                    'total_amount' => (int) $item['sub_total'],
                    'food_item_id' => $item['food_item_id'],
                    'food_item_attribute_id' => $item['id'],
                    'food_category_id' => $product->food_category_id,
                ]);
            } else { // If it's a regular food item
                $product = FoodItem::findOrFail($item['id']);
                SaleItem::create([
                    'sale_id' => $sale->id,
                    'item_data' => $product,
                    'item_name' => $item['name'],
                    'quantity' => $item['qty'],
                    'price' => $item['price'],
                    'total_amount' => (int) $item['sub_total'],
                    'food_item_attribute_id' => null,
                    'food_item_id' => $item['id'],
                    'food_category_id' => $product->food_category_id,
                ]);
            }
        }
    }

    public function updatePay(SalePaymentUpdateRequest $request, Sale $sale): JsonResponse
    {
        $sale->update([
            'payment_method_id' => $request->payment_method_id,
            'is_paid' => $request->is_paid
        ]);
        return response()->json(['message' => __('Data updated successfully')]);
    }

    protected function handleRequestWithOrderType($request)
    {
        $validated = $request->validated();
        // Handle order type specific data
        switch ($validated['order_type']) {
            case 'dining':
                $validated['pickup_point_id'] = null;
                $validated['shipping_address'] = null;
                break;
            case 'pickup':
                $validated['table_id'] = null;
                $validated['shipping_address'] = null;
                break;
            case 'dilivery':
                $validated['table_id'] = null;
                $validated['pickup_point_id'] = null;
                break;
        }
        return $validated;
    }
}
