<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Company;
use App\Models\Product;
use App\Models\PurchaseOrder;
use App\Models\Supplier;
use App\Services\ReminderService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use Illuminate\View\View;

class PurchaseOrderController extends Controller
{
    public function __construct(
        private ReminderService $reminderService
    ) {}

    /**
     * Display a listing of the resource.
     */
    public function index(Request $request): View
    {
        $perPage = $request->get('per_page', 10);
        $search = $request->get('search', '');

        $query = PurchaseOrder::with(['supplier', 'company', 'creator']);

        if (! empty($search)) {
            $query->where(function ($q) use ($search) {
                $q->where('order_number', 'like', "%{$search}%")
                    ->orWhereHas('supplier', function ($supplierQuery) use ($search) {
                        $supplierQuery->where('name', 'like', "%{$search}%")
                            ->orWhere('email', 'like', "%{$search}%");
                    });
            });
        }

        $purchaseOrders = $query->orderBy('created_at', 'desc')->paginate($perPage);

        return view('admin.purchase-orders.index', [
            'purchaseOrders' => $purchaseOrders,
            'perPage' => $perPage,
            'search' => $search,
        ]);
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create(): View
    {
        $nextOrderNumber = PurchaseOrder::generateOrderNumber();
        $companySettings = \App\Models\CompanySetting::getSettings();
        $localizationSettings = \App\Models\LocalizationSetting::getSettings();
        $currencies = \App\Models\Currency::where('is_active', true)->orderBy('is_default', 'desc')->orderBy('name')->get();
        $defaultCurrency = $localizationSettings->default_currency ?? 'USD';
        $defaultCurrencyModel = $currencies->where('code', $defaultCurrency)->first() ?? \App\Models\Currency::getDefault();

        return view('admin.purchase-orders.create', [
            'nextOrderNumber' => $nextOrderNumber,
            'companySettings' => $companySettings,
            'currencies' => $currencies,
            'defaultCurrency' => $defaultCurrency,
            'defaultCurrencyModel' => $defaultCurrencyModel,
        ]);
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'order_number' => 'required|string|unique:purchase_orders,order_number',
            'order_date' => 'required|date',
            'status' => 'required|in:new,pending,approved,rejected,completed,cancelled',
            'company_id' => 'nullable|exists:companies,id',
            'supplier_id' => 'required|exists:suppliers,id',
            'items' => 'required|array|min:1',
            'items.*.product_name' => 'required|string',
            'items.*.quantity' => 'required|numeric|min:0.01',
            'items.*.rate' => 'required|numeric|min:0',
            'items.*.discount' => 'nullable|numeric|min:0',
            'items.*.tax' => 'nullable|numeric|min:0',
            'items.*.unit' => 'nullable|string',
            'payment_method' => 'nullable|string',
            'notes' => 'nullable|string',
            'terms' => 'nullable|string',
            'bank_details' => 'nullable|string',
            'signature_type' => 'nullable|in:manual,esignature',
            'signature_id' => 'nullable|exists:signatures,id',
        ]);

        try {
            DB::beginTransaction();

            // Calculate totals
            $amount = 0;
            $totalTax = 0;
            $totalDiscount = 0;

            foreach ($validated['items'] as $item) {
                $itemSubtotal = $item['quantity'] * $item['rate'];
                $itemDiscount = $item['discount'] ?? 0;
                $itemTax = ($itemSubtotal - $itemDiscount) * (($item['tax'] ?? 0) / 100);

                $amount += $itemSubtotal;
                $totalDiscount += $itemDiscount;
                $totalTax += $itemTax;
            }

            $total = $amount - $totalDiscount + $totalTax;

            // Create purchase order
            $purchaseOrder = PurchaseOrder::create([
                'order_number' => $validated['order_number'],
                'order_date' => $validated['order_date'],
                'status' => $validated['status'],
                'company_id' => $validated['company_id'],
                'supplier_id' => $validated['supplier_id'],
                'amount' => $amount,
                'tax_amount' => $totalTax,
                'discount_amount' => $totalDiscount,
                'total' => $total,
                'payment_method' => $validated['payment_method'] ?? 'cash',
                'notes' => $validated['notes'] ?? null,
                'terms' => $validated['terms'] ?? null,
                'bank_details' => $validated['bank_details'] ?? null,
                'signature_type' => $validated['signature_type'] ?? 'manual',
                'signature_id' => $validated['signature_id'] ?? null,
                'created_by' => Auth::id(),
            ]);

            // Create items
            foreach ($validated['items'] as $index => $item) {
                $itemSubtotal = $item['quantity'] * $item['rate'];
                $itemDiscount = $item['discount'] ?? 0;
                $itemTax = ($itemSubtotal - $itemDiscount) * (($item['tax'] ?? 0) / 100);
                $itemAmount = $itemSubtotal - $itemDiscount + $itemTax;

                $purchaseOrder->items()->create([
                    'product_id' => $item['product_id'] ?? null,
                    'description' => $item['product_name'],
                    'unit' => $item['unit'] ?? null,
                    'quantity' => $item['quantity'],
                    'rate' => $item['rate'],
                    'discount' => $itemDiscount,
                    'tax_rate' => $item['tax'] ?? 0,
                    'tax_amount' => $itemTax,
                    'amount' => $itemAmount,
                    'sort_order' => $index,
                ]);
            }

            DB::commit();

            try {
                $this->reminderService->sendPurchaseOrderCreated($purchaseOrder->fresh('supplier'));
            } catch (\Throwable) {
            }

            return redirect()->route('admin.purchase-orders.index')
                ->with('success', 'Purchase order created successfully');
        } catch (\Exception $e) {
            DB::rollBack();

            return back()
                ->withInput()
                ->withErrors(['error' => 'Failed to create purchase order: '.$e->getMessage()]);
        }
    }

    /**
     * Display the specified resource.
     */
    public function show(PurchaseOrder $purchaseOrder): View
    {
        $purchaseOrder->load(['supplier', 'company', 'items', 'creator', 'signature']);

        return view('admin.purchase-orders.show', [
            'purchaseOrder' => $purchaseOrder,
        ]);
    }

    /**
     * Show the form for editing the specified resource.
     */
    public function edit(PurchaseOrder $purchaseOrder): View
    {
        $purchaseOrder->load(['items', 'company', 'supplier', 'signature']);
        $companySettings = \App\Models\CompanySetting::getSettings();
        $localizationSettings = \App\Models\LocalizationSetting::getSettings();
        $currencies = \App\Models\Currency::where('is_active', true)->orderBy('is_default', 'desc')->orderBy('name')->get();
        $defaultCurrency = $localizationSettings->default_currency ?? 'USD';
        $defaultCurrencyModel = $currencies->where('code', $defaultCurrency)->first() ?? \App\Models\Currency::getDefault();

        return view('admin.purchase-orders.create', [
            'purchaseOrder' => $purchaseOrder,
            'nextOrderNumber' => $purchaseOrder->order_number,
            'companySettings' => $companySettings,
            'currencies' => $currencies,
            'defaultCurrency' => $defaultCurrency,
            'defaultCurrencyModel' => $defaultCurrencyModel,
        ]);
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, PurchaseOrder $purchaseOrder): RedirectResponse
    {
        $validated = $request->validate([
            'order_number' => [
                'required',
                'string',
                Rule::unique('purchase_orders', 'order_number')->ignore($purchaseOrder->id),
            ],
            'order_date' => 'required|date',
            'status' => 'required|in:new,pending,approved,rejected,completed,cancelled',
            'company_id' => 'nullable|exists:companies,id',
            'supplier_id' => 'required|exists:suppliers,id',
            'items' => 'required|array|min:1',
            'items.*.product_id' => 'nullable|exists:products,id',
            'items.*.product_name' => 'required|string',
            'items.*.quantity' => 'required|numeric|min:0.01',
            'items.*.rate' => 'required|numeric|min:0',
            'items.*.discount' => 'nullable|numeric|min:0',
            'items.*.tax' => 'nullable|numeric|min:0',
            'items.*.unit' => 'nullable|string',
            'payment_method' => 'nullable|string',
            'notes' => 'nullable|string',
            'terms' => 'nullable|string',
            'bank_details' => 'nullable|string',
            'signature_type' => 'nullable|in:manual,esignature',
            'signature_id' => 'nullable|exists:signatures,id',
        ]);

        try {
            DB::beginTransaction();

            $amount = 0;
            $totalTax = 0;
            $totalDiscount = 0;

            foreach ($validated['items'] as $item) {
                $itemSubtotal = $item['quantity'] * $item['rate'];
                $itemDiscount = $item['discount'] ?? 0;
                $itemTax = ($itemSubtotal - $itemDiscount) * (($item['tax'] ?? 0) / 100);

                $amount += $itemSubtotal;
                $totalDiscount += $itemDiscount;
                $totalTax += $itemTax;
            }

            $total = $amount - $totalDiscount + $totalTax;

            $purchaseOrder->update([
                'order_number' => $validated['order_number'],
                'order_date' => $validated['order_date'],
                'status' => $validated['status'],
                'company_id' => $validated['company_id'],
                'supplier_id' => $validated['supplier_id'],
                'amount' => $amount,
                'tax_amount' => $totalTax,
                'discount_amount' => $totalDiscount,
                'total' => $total,
                'payment_method' => $validated['payment_method'] ?? 'cash',
                'notes' => $validated['notes'] ?? null,
                'terms' => $validated['terms'] ?? null,
                'bank_details' => $validated['bank_details'] ?? null,
                'signature_type' => $validated['signature_type'] ?? 'manual',
                'signature_id' => $validated['signature_id'] ?? null,
            ]);

            $purchaseOrder->items()->delete();

            foreach ($validated['items'] as $index => $item) {
                $itemSubtotal = $item['quantity'] * $item['rate'];
                $itemDiscount = $item['discount'] ?? 0;
                $itemTax = ($itemSubtotal - $itemDiscount) * (($item['tax'] ?? 0) / 100);
                $itemAmount = $itemSubtotal - $itemDiscount + $itemTax;

                $purchaseOrder->items()->create([
                    'product_id' => $item['product_id'] ?? null,
                    'description' => $item['product_name'],
                    'unit' => $item['unit'] ?? null,
                    'quantity' => $item['quantity'],
                    'rate' => $item['rate'],
                    'discount' => $itemDiscount,
                    'tax_rate' => $item['tax'] ?? 0,
                    'tax_amount' => $itemTax,
                    'amount' => $itemAmount,
                    'sort_order' => $index,
                ]);
            }

            DB::commit();

            return redirect()->route('admin.purchase-orders.index')
                ->with('success', 'Purchase order updated successfully');
        } catch (\Exception $e) {
            DB::rollBack();

            return back()
                ->withInput()
                ->withErrors(['error' => 'Failed to update purchase order: '.$e->getMessage()]);
        }
    }

    /**
     * API: Get companies for dropdown (AJAX)
     */
    public function getCompanies(Request $request): JsonResponse
    {
        try {
            $query = Company::where('is_active', true);

            $search = $request->get('search', '');
            if (! empty($search)) {
                $query->where(function ($q) use ($search) {
                    $q->where('name', 'like', "%{$search}%")
                        ->orWhere('email', 'like', "%{$search}%")
                        ->orWhere('phone', 'like', "%{$search}%");
                });
            }

            $companies = $query->orderBy('name', 'asc')->limit(50)->get();

            return response()->json([
                'success' => true,
                'companies' => $companies->map(function ($company) {
                    return [
                        'id' => $company->id,
                        'name' => $company->name,
                        'email' => $company->email ?? '',
                        'phone' => $company->phone ?? '',
                        'address' => $company->address ?? '',
                        'city' => $company->city ?? '',
                        'state' => $company->state ?? '',
                        'zip' => $company->zip ?? '',
                        'country' => $company->country ?? '',
                        'logo' => $company->logo_url,
                        'logo_path' => $company->logo,
                    ];
                })->toArray(),
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error fetching companies: '.$e->getMessage(),
                'companies' => [],
            ], 500);
        }
    }

    /**
     * API: Get suppliers for dropdown (AJAX)
     */
    public function getSuppliers(Request $request): JsonResponse
    {
        try {
            $query = Supplier::where('is_active', true);

            $search = $request->get('search', '');
            if (! empty($search)) {
                $query->where(function ($q) use ($search) {
                    $q->where('name', 'like', "%{$search}%")
                        ->orWhere('email', 'like', "%{$search}%")
                        ->orWhere('phone', 'like', "%{$search}%");
                });
            }

            $suppliers = $query->orderBy('name', 'asc')->limit(50)->get();

            return response()->json([
                'success' => true,
                'suppliers' => $suppliers->map(function ($supplier) {
                    return [
                        'id' => $supplier->id,
                        'name' => $supplier->name,
                        'email' => $supplier->email ?? '',
                        'phone' => $supplier->phone ?? '',
                        'address' => $supplier->address ?? '',
                        'city' => $supplier->city ?? '',
                        'state' => $supplier->state ?? '',
                        'zip' => $supplier->zip ?? '',
                        'country' => $supplier->country ?? '',
                        'image' => $supplier->image_url,
                        'image_path' => $supplier->image,
                    ];
                })->toArray(),
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error fetching suppliers: '.$e->getMessage(),
                'suppliers' => [],
            ], 500);
        }
    }

    /**
     * API: Get products for dropdown (AJAX)
     */
    public function getProducts(Request $request): JsonResponse
    {
        try {
            $query = Product::with(['unit', 'tax'])->where('status', true);

            $search = $request->get('search', '');
            if (! empty($search)) {
                $query->where(function ($q) use ($search) {
                    $q->where('name', 'like', "%{$search}%")
                        ->orWhere('code', 'like', "%{$search}%")
                        ->orWhere('barcode', 'like', "%{$search}%");
                });
            }

            $products = $query->orderBy('name', 'asc')->limit(50)->get();

            return response()->json([
                'success' => true,
                'products' => $products->map(function ($product) {
                    return [
                        'id' => $product->id,
                        'name' => $product->name,
                        'code' => $product->code ?? '',
                        'barcode' => $product->barcode ?? '',
                        'unit' => $product->unit ? $product->unit->short_name : '',
                        'purchase_price' => $product->purchase_price ?? 0,
                        'tax_rate' => $product->tax ? $product->tax->rate : 0,
                    ];
                })->toArray(),
            ]);
        } catch (\Exception $e) {
            \Log::error('Error fetching products: '.$e->getMessage(), [
                'trace' => $e->getTraceAsString(),
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Error fetching products: '.$e->getMessage(),
                'products' => [],
            ], 500);
        }
    }

    /**
     * API: Get company settings (for BILL FROM)
     */
    public function getCompanySettings(): JsonResponse
    {
        try {
            $companySettings = \App\Models\CompanySetting::getSettings();

            $logoUrl = null;
            if ($companySettings->company_logo) {
                if (\Illuminate\Support\Facades\Storage::disk('public')->exists($companySettings->company_logo)) {
                    $logoUrl = asset('storage/'.$companySettings->company_logo);
                }
            }

            return response()->json([
                'success' => true,
                'company' => [
                    'name' => $companySettings->company_name ?? '',
                    'email' => $companySettings->company_email ?? '',
                    'phone' => $companySettings->company_phone ?? '',
                    'fax' => $companySettings->company_fax ?? '',
                    'address' => $companySettings->company_address ?? '',
                    'city' => $companySettings->company_city ?? '',
                    'state' => $companySettings->company_state ?? '',
                    'zip' => $companySettings->company_zip ?? '',
                    'country' => $companySettings->company_country ?? '',
                    'tax_id' => $companySettings->company_tax_id ?? '',
                    'registration_number' => $companySettings->company_registration_number ?? '',
                    'logo' => $logoUrl,
                    'logo_path' => $companySettings->company_logo,
                ],
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error fetching company settings: '.$e->getMessage(),
                'company' => null,
            ], 500);
        }
    }

    /**
     * API: Get bank accounts for dropdown (AJAX)
     */
    public function getBankAccounts(): JsonResponse
    {
        try {
            $bankAccounts = \App\Models\BankAccount::where('is_active', true)
                ->orderBy('account_name', 'asc')
                ->get();

            return response()->json([
                'success' => true,
                'bank_accounts' => $bankAccounts->map(function ($account) {
                    return [
                        'id' => $account->id,
                        'account_name' => $account->account_name,
                        'account_number' => $account->account_number,
                        'bank_name' => $account->bank_name,
                    ];
                })->toArray(),
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error fetching bank accounts: '.$e->getMessage(),
                'bank_accounts' => [],
            ], 500);
        }
    }

    /**
     * API: Get signatures for dropdown (AJAX)
     */
    public function getSignatures(): JsonResponse
    {
        try {
            $signatures = \App\Models\Signature::where('is_active', true)
                ->orderBy('name', 'asc')
                ->get();

            return response()->json([
                'success' => true,
                'signatures' => $signatures->map(function ($signature) {
                    return [
                        'id' => $signature->id,
                        'name' => $signature->name,
                    ];
                })->toArray(),
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error fetching signatures: '.$e->getMessage(),
                'signatures' => [],
            ], 500);
        }
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(PurchaseOrder $purchaseOrder): RedirectResponse
    {
        try {
            $purchaseOrder->delete();

            return redirect()->route('admin.purchase-orders.index')
                ->with('success', 'Purchase order deleted successfully.');
        } catch (\Exception $e) {
            return redirect()->route('admin.purchase-orders.index')
                ->withErrors(['error' => 'Failed to delete purchase order: '.$e->getMessage()]);
        }
    }
}
