<?php

namespace App\Http\Controllers;

use App\Models\Account;
use App\Models\FactoryInvoice;
use App\Models\FactoryInvoiceItem;
use App\Services\NumberGenerationService;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\View\View;
use Illuminate\Support\Facades\DB;
use Yajra\DataTables\Facades\DataTables;

class FactoryPOSController extends Controller
{
    protected $numberGenerationService;

    public function __construct(NumberGenerationService $numberGenerationService)
    {
        $this->numberGenerationService = $numberGenerationService;
    }

    /**
     * Display a listing of factory invoices
     */
    public function index(): View
    {
        // Get customers for filter dropdown
        $customers = Account::where('model_type', 'contact')
                           ->whereHas('contact', function($q) {
                               $q->whereIn('type', ['customer', 'shop_manager']);
                           })
                           ->where('is_active', true)
                           ->orderBy('name')
                           ->get();

        return view('factory-pos.index', compact('customers'));
    }

    /**
     * Get data for DataTables
     */
    public function getData(Request $request)
    {
        $query = FactoryInvoice::with(['customer', 'supervisingEmployee', 'warehousePicker', 'deliveryMan']);

        // Apply filters
        if ($request->filled('status') && $request->status !== 'all') {
            $query->where('status', $request->status);
        }

        if ($request->filled('customer_id')) {
            $query->where('customer_account_id', $request->customer_id);
        }

        if ($request->filled('date_from') && $request->filled('date_to')) {
            $query->whereBetween('invoice_date', [$request->date_from, $request->date_to]);
        }

        return DataTables::of($query)
            ->addColumn('invoice_number', function ($invoice) {
                return $invoice->invoice_number;
            })
            ->addColumn('customer_name', function ($invoice) {
                return $invoice->customer->name ?? 'N/A';
            })
            ->addColumn('supervisor', function ($invoice) {
                return $invoice->supervisingEmployee->name ?? 'N/A';
            })
            ->addColumn('total_ordered_amount', function ($invoice) {
                return $invoice->total_ordered_amount;
            })
            ->addColumn('discount_amount', function ($invoice) {
                return $invoice->discount_amount;
            })
            ->addColumn('net_total', function ($invoice) {
                return $invoice->net_total;
            })
            ->addColumn('total_delivered_amount', function ($invoice) {
                return $invoice->total_delivered_amount;
            })
            ->addColumn('created_at', function ($invoice) {
                return $invoice->created_at;
            })
            ->addColumn('status_badge', function ($invoice) {
                $badges = [
                    'warehouse_pending' => '<span class="badge bg-warning">Warehouse Pending</span>',
                    'picked' => '<span class="badge bg-info">Picked</span>',
                    'delivered' => '<span class="badge bg-primary">Delivered</span>',
                    'completed' => '<span class="badge bg-success">Completed</span>',
                ];
                return $badges[$invoice->status] ?? '<span class="badge bg-secondary">' . ucfirst($invoice->status) . '</span>';
            })
            ->addColumn('actions', function ($invoice) {
                $actions = '<a href="' . route('factory-pos.show', $invoice) . '" class="btn btn-sm btn-info">View</a>';

                // if ($invoice->isPendingWarehouse()) {
                //     $actions .= ' <a href="' . route('factory-pos.edit', $invoice) . '" class="btn btn-sm btn-warning">Edit</a>';
                // }

                return $actions;
            })
            ->rawColumns(['status_badge', 'actions'])
            ->make(true);
    }

    /**
     * Show the form for creating a new invoice
     */
    public function create(): View
    {
        // Get customers (accounts with model_type = contact and contact type = customer or shop_manager)
        $customers = Account::where('model_type', 'contact')
                           ->whereHas('contact', function($q) {
                               $q->whereIn('type', ['customer', 'shop_manager']);
                           })
                           ->where('is_active', true)
                           ->orderBy('name')
                           ->get();

        // Get supervising employees
        $employees = Account::where('model_type', 'contact')
                           ->whereHas('contact', function($q) {
                               $q->where('type', 'employee');
                           })
                           ->where('is_active', true)
                           ->orderBy('name')
                           ->get();

        return view('factory-pos.create', compact('customers', 'employees'));
    }

    /**
     * Store a newly created invoice
     */
    public function store(Request $request): RedirectResponse
    {
        $request->validate([
            'customer_id' => 'required|exists:accounts,id',
            'supervising_employee_id' => 'required|exists:accounts,id',
            'discount_amount' => 'nullable|numeric|min:0',
            'discount_percentage' => 'nullable|numeric|min:0|max:100',
            'items' => 'required|array|min:1',
            'items.*.item_id' => 'required|exists:accounts,id',
            'items.*.quantity' => 'required|numeric|min:0.01',
            'items.*.unit_price' => 'required|numeric|min:0',
        ]);

        DB::transaction(function () use ($request) {
            // Generate invoice number
            $invoiceNumber = $this->numberGenerationService->generateNumber('factory_invoice', 'FI');

            $totalAmount = 0;

            // Calculate total from items first
            foreach ($request->items as $itemData) {
                $quantity = $itemData['quantity'];
                $unitPrice = $itemData['unit_price'];
                $total = $quantity * $unitPrice;
                $totalAmount += $total;
            }

            // Calculate discount
            $discountAmount = $request->discount_amount ?? 0;
            $discountPercentage = $request->discount_percentage ?? 0;

            // If percentage is provided, calculate discount amount
            if ($discountPercentage > 0) {
                $discountAmount = ($totalAmount * $discountPercentage) / 100;
            }

            $netTotal = $totalAmount - $discountAmount;

            // Create invoice
            $invoice = FactoryInvoice::create([
                'invoice_number' => $invoiceNumber,
                'customer_account_id' => $request->customer_id,
                'supervising_employee_account_id' => $request->supervising_employee_id,
                'total_ordered_amount' => $totalAmount,
                'discount_amount' => $discountAmount,
                'discount_percentage' => $discountPercentage > 0 ? $discountPercentage : null,
                'net_total' => $netTotal,
                'status' => 'warehouse_pending',
                'invoice_date' => now(),
            ]);

            // Create invoice items
            foreach ($request->items as $itemData) {
                $quantity = $itemData['quantity'];
                $unitPrice = $itemData['unit_price'];
                $total = $quantity * $unitPrice;

                FactoryInvoiceItem::create([
                    'factory_invoice_id' => $invoice->id,
                    'item_account_id' => $itemData['item_id'],
                    'ordered_quantity' => $quantity,
                    'ordered_unit_price' => $unitPrice,
                    'ordered_total' => $total,
                ]);
            }
        });

        return redirect()->route('factory-pos.index')->with('success', 'Factory invoice created successfully');
    }

    /**
     * Store factory invoice via API
     */
    public function storeApi(Request $request)
    {
        $request->validate([
            'customer_id' => 'required|exists:accounts,id',
            'supervising_employee_id' => 'required|exists:accounts,id',
            'discount_amount' => 'nullable|numeric|min:0',
            'discount_percentage' => 'nullable|numeric|min:0|max:100',
            'items' => 'required|array|min:1',
            'items.*.item_id' => 'required|exists:accounts,id',
            'items.*.quantity' => 'required|numeric|min:0.01',
            'items.*.unit_price' => 'required|numeric|min:0',
        ]);

        try {
            DB::transaction(function () use ($request) {
                // Simple invoice number generation (without service class)
                $currentYear = now()->format('Y');
                $currentMonth = now()->format('m');

                // Get last invoice number for current month
                $lastInvoice = FactoryInvoice::where('invoice_number', 'like', "FI-{$currentYear}{$currentMonth}-%")
                    ->orderBy('invoice_number', 'desc')
                    ->first();

                $sequence = 1;
                if ($lastInvoice) {
                    $parts = explode('-', $lastInvoice->invoice_number);
                    $sequence = (int) end($parts) + 1;
                }

                $invoiceNumber = sprintf("FI-%s%s-%03d", $currentYear, $currentMonth, $sequence);

                $totalAmount = 0;

                // Calculate total from items first
                foreach ($request->items as $itemData) {
                    $quantity = $itemData['quantity'];
                    $unitPrice = $itemData['unit_price'];
                    $total = $quantity * $unitPrice;
                    $totalAmount += $total;
                }

                // Calculate discount
                $discountAmount = $request->discount_amount ?? 0;
                $discountPercentage = $request->discount_percentage ?? 0;

                // If percentage is provided, calculate discount amount
                if ($discountPercentage > 0) {
                    $discountAmount = ($totalAmount * $discountPercentage) / 100;
                }

                $netTotal = $totalAmount - $discountAmount;

                // Create invoice
                $invoice = FactoryInvoice::create([
                    'invoice_number' => $invoiceNumber,
                    'customer_account_id' => $request->customer_id,
                    'supervising_employee_account_id' => $request->supervising_employee_id,
                    'total_ordered_amount' => $totalAmount,
                    'discount_amount' => $discountAmount,
                    'discount_percentage' => $discountPercentage > 0 ? $discountPercentage : null,
                    'net_total' => $netTotal,
                    'status' => 'warehouse_pending',
                    'invoice_date' => now(),
                ]);

                // Create invoice items
                foreach ($request->items as $itemData) {
                    $quantity = $itemData['quantity'];
                    $unitPrice = $itemData['unit_price'];
                    $total = $quantity * $unitPrice;

                    FactoryInvoiceItem::create([
                        'factory_invoice_id' => $invoice->id,
                        'item_account_id' => $itemData['item_id'],
                        'ordered_quantity' => $quantity,
                        'ordered_unit_price' => $unitPrice,
                        'ordered_total' => $total,
                    ]);
                }
            });

            return response()->json([
                'success' => true,
                'data' => null,
                'message' => 'Factory invoice created successfully'
            ]);

        } catch (\Illuminate\Validation\ValidationException $e) {
            return response()->json([
                'success' => false,
                'data' => null,
                'message' => 'Validation failed',
                'errors' => $e->errors()
            ], 422);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'data' => null,
                'message' => 'Failed to create invoice: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Display the specified invoice
     */
    public function show($id): View
    {
        $invoice = FactoryInvoice::findOrFail($id);
        $invoice->load(['customer', 'supervisingEmployee', 'items.item', 'warehousePicker', 'deliveryMan', 'deliveryReceipts.items']);
        return view('factory-pos.show', compact('invoice'));
    }

    /**
     * Show the form for editing the invoice (only if warehouse_pending)
     */
    public function edit($id): View
    {
        $invoice = FactoryInvoice::findOrFail($id);

        if (!$invoice->isPendingWarehouse()) {
            abort(403, 'Cannot edit invoice that has been processed');
        }

        $customers = Account::where('model_type', 'contact')
                           ->whereHas('contact', function($q) {
                               $q->whereIn('type', ['customer', 'shop_manager']);
                           })
                           ->where('is_active', true)
                           ->orderBy('name')
                           ->get();

        $employees = Account::where('model_type', 'contact')
                           ->whereHas('contact', function($q) {
                               $q->where('type', 'employee');
                           })
                           ->where('is_active', true)
                           ->orderBy('name')
                           ->get();

        return view('factory-pos.edit', compact('invoice', 'customers', 'employees'));
    }

    /**
     * Update the specified invoice
     */
    public function update(Request $request, $id): RedirectResponse
    {
        $invoice = FactoryInvoice::findOrFail($id);

        if (!$invoice->isPendingWarehouse()) {
            abort(403, 'Cannot edit invoice that has been processed');
        }

        $request->validate([
            'customer_id' => 'required|exists:accounts,id',
            'supervising_employee_id' => 'required|exists:accounts,id',
            'discount_amount' => 'nullable|numeric|min:0',
            'discount_percentage' => 'nullable|numeric|min:0|max:100',
            'items' => 'required|array|min:1',
            'items.*.item_id' => 'required|exists:accounts,id',
            'items.*.quantity' => 'required|numeric|min:0.01',
            'items.*.unit_price' => 'required|numeric|min:0',
        ]);

        DB::transaction(function () use ($request, $invoice) {
            $totalAmount = 0;

            // Calculate total from items first
            foreach ($request->items as $itemData) {
                $quantity = $itemData['quantity'];
                $unitPrice = $itemData['unit_price'];
                $total = $quantity * $unitPrice;
                $totalAmount += $total;
            }

            // Calculate discount
            $discountAmount = $request->discount_amount ?? 0;
            $discountPercentage = $request->discount_percentage ?? 0;

            // If percentage is provided, calculate discount amount
            if ($discountPercentage > 0) {
                $discountAmount = ($totalAmount * $discountPercentage) / 100;
            }

            $netTotal = $totalAmount - $discountAmount;

            // Update invoice
            $invoice->update([
                'customer_account_id' => $request->customer_id,
                'supervising_employee_account_id' => $request->supervising_employee_id,
                'total_ordered_amount' => $totalAmount,
                'discount_amount' => $discountAmount,
                'discount_percentage' => $discountPercentage > 0 ? $discountPercentage : null,
                'net_total' => $netTotal,
            ]);

            // Delete existing items
            $invoice->items()->delete();

            // Create new items
            foreach ($request->items as $itemData) {
                $quantity = $itemData['quantity'];
                $unitPrice = $itemData['unit_price'];
                $total = $quantity * $unitPrice;

                FactoryInvoiceItem::create([
                    'factory_invoice_id' => $invoice->id,
                    'item_account_id' => $itemData['item_id'],
                    'ordered_quantity' => $quantity,
                    'ordered_unit_price' => $unitPrice,
                    'ordered_total' => $total,
                ]);
            }
        });

        return redirect()->route('factory-pos.show', $invoice)->with('success', 'Factory invoice updated successfully');
    }

    /**
     * Get items for autocomplete
     */
    public function getItems(Request $request)
    {
        $search = $request->get('q', '');
        $showAll = $request->boolean('show_all', false);

        // Only show finished goods items from "finished-goods" chart of account (ID 53)
        $query = Account::where('model_type', 'Item')
                       ->where('is_active', true)
                    //    ->where('chart_of_account_id', 53); // Only from "finished-goods" chart of account
                    // ->whereHas('chartOfAccount', function ($q) {
                    //     $q->where('id', 53)
                    //       ->orWhere('parent_id', 53);
                    // });
                    ->whereHas('chartOfAccount', function ($q) {
                        $q->where('parent_id', 53);
                    });
        // Apply search filter only if not showing all
        if (!$showAll && !empty($search)) {
            $query->where('name', 'like', "%{$search}%");
        }
        // dd($query->toSql());
        $items = $query->limit($showAll ? 50 : 10) // Show more items when showing all
                      ->get(['accounts.id', 'accounts.name', 'accounts.sku']);

        return response()->json([
            'results' => $items->map(function ($item) {
                return [
                    'id' => $item->id,
                    'text' => $item->name . ' (' . ($item->sku ?: 'No SKU') . ')',
                    'name' => $item->name,
                    'sku' => $item->sku,
                ];
            })
        ]);
    }
}
