<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\BankAccount;
use App\Models\Company;
use App\Models\Purchase;
use App\Models\Signature;
use App\Models\Supplier;
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 PurchaseController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(Request $request): View
    {
        $perPage = $request->get('per_page', 10);
        $search = $request->get('search', '');

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

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

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

        return view('admin.purchases.index', [
            'purchases' => $purchases,
            'perPage' => $perPage,
            'search' => $search,
        ]);
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create(): View
    {
        $nextPurchaseNumber = Purchase::generatePurchaseNumber();
        $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.purchases.create', [
            'purchase' => null,
            'nextPurchaseNumber' => $nextPurchaseNumber,
            'companySettings' => $companySettings,
            'currencies' => $currencies,
            'defaultCurrency' => $defaultCurrency,
            'defaultCurrencyModel' => $defaultCurrencyModel,
        ]);
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'purchase_number' => 'required|string|unique:purchases,purchase_number',
            'purchase_date' => 'required|date',
            'order_date' => 'nullable|date',
            'status' => 'required|in:new,pending,partially_paid,completed,cancelled',
            'company_id' => 'nullable|exists:companies,id',
            'supplier_id' => 'required',
            'bank_account_id' => 'nullable|exists:bank_accounts,id',
            'signature_type' => 'nullable|in:manual,esignature',
            'signature_id' => 'nullable|exists:signatures,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',
        ]);

        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;

            // Handle supplier_id - could be from suppliers or customers table
            $supplierId = $validated['supplier_id'];
            $supplierType = $request->input('supplier_type', 'supplier'); // 'supplier' or 'customer'

            // Validate supplier/customer exists
            if ($supplierType === 'customer') {
                $customer = \App\Models\Customer::find($supplierId);
                if (! $customer) {
                    throw new \Exception('Customer not found');
                }
                // Create a supplier record from customer if it doesn't exist
                $supplier = Supplier::where('name', $customer->name)
                    ->where('email', $customer->email)
                    ->first();

                if (! $supplier) {
                    $supplier = Supplier::create([
                        'name' => $customer->name,
                        'email' => $customer->email,
                        'phone' => $customer->phone,
                        'address' => $customer->address,
                        'city' => $customer->city,
                        'state' => $customer->state,
                        'zip' => $customer->zip,
                        'country' => $customer->country,
                        'image' => $customer->image,
                        'balance' => 0,
                        'mode' => 'credit',
                        'is_active' => true,
                        'created_by' => Auth::id(),
                    ]);
                }
                $supplierId = $supplier->id;
            } else {
                $supplier = Supplier::find($supplierId);
                if (! $supplier) {
                    throw new \Exception('Supplier not found');
                }
            }

            // Create purchase
            $purchase = Purchase::create([
                'purchase_number' => $validated['purchase_number'],
                'purchase_date' => $validated['purchase_date'],
                'order_date' => $validated['order_date'] ?? null,
                'status' => $validated['status'],
                'company_id' => $validated['company_id'] ?? null, // Can be null if using company settings
                'supplier_id' => $supplierId, // Now always a valid supplier ID
                'amount' => $amount,
                'tax_amount' => $totalTax,
                'discount_amount' => $totalDiscount,
                'total' => $total,
                'payment_method' => $validated['payment_method'] ?? 'cash',
                'bank_account_id' => $validated['bank_account_id'] ?? null,
                'notes' => $validated['notes'] ?? null,
                'terms' => $validated['terms'] ?? 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;

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

            DB::commit();

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

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

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

            $logoUrl = null;
            if ($companySettings->company_logo) {
                if (\Illuminate\Support\Facades\Storage::disk('public')->exists($companySettings->company_logo)) {
                    // Use asset() helper which uses the current request's domain
                    $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 companies for dropdown (AJAX)
     */
    public function getCompanies(Request $request): \Illuminate\Http\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 and customers for dropdown (AJAX)
     */
    public function getSuppliers(Request $request): \Illuminate\Http\JsonResponse
    {
        try {
            $search = $request->get('search', '');
            $suppliers = collect();
            $customers = collect();

            // Fetch suppliers
            $supplierQuery = Supplier::where('is_active', true);
            if (! empty($search)) {
                $supplierQuery->where(function ($q) use ($search) {
                    $q->where('name', 'like', "%{$search}%")
                        ->orWhere('email', 'like', "%{$search}%")
                        ->orWhere('phone', 'like', "%{$search}%");
                });
            }
            $suppliers = $supplierQuery->orderBy('name', 'asc')->limit(50)->get();

            // Fetch customers
            $customerQuery = \App\Models\Customer::where('is_active', true);
            if (! empty($search)) {
                $customerQuery->where(function ($q) use ($search) {
                    $q->where('name', 'like', "%{$search}%")
                        ->orWhere('email', 'like', "%{$search}%")
                        ->orWhere('phone', 'like', "%{$search}%")
                        ->orWhere('company', 'like', "%{$search}%");
                });
            }
            $customers = $customerQuery->orderBy('name', 'asc')->limit(50)->get();

            // Combine and format
            $allSuppliers = $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,
                    'type' => 'supplier',
                ];
            });

            $allCustomers = $customers->map(function ($customer) {
                $imageUrl = '';
                if ($customer->image) {
                    if (\Illuminate\Support\Facades\Storage::disk('public')->exists($customer->image)) {
                        // Use asset() helper which uses the current request's domain
                        $imageUrl = asset('storage/'.$customer->image);
                    }
                }

                return [
                    'id' => $customer->id,
                    'name' => $customer->name,
                    'email' => $customer->email ?? '',
                    'phone' => $customer->phone ?? '',
                    'company' => $customer->company ?? '',
                    'address' => $customer->address ?? '',
                    'city' => $customer->city ?? '',
                    'state' => $customer->state ?? '',
                    'zip' => $customer->zip ?? '',
                    'country' => $customer->country ?? '',
                    'image' => $imageUrl,
                    'image_path' => $customer->image,
                    'type' => 'customer',
                ];
            });

            // Merge suppliers and customers
            $allResults = $allSuppliers->merge($allCustomers)->sortBy('name')->values();

            return response()->json([
                'success' => true,
                'suppliers' => $allResults->toArray(),
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error fetching suppliers: '.$e->getMessage(),
                'suppliers' => [],
            ], 500);
        }
    }

    /**
     * API: Get bank accounts for dropdown (AJAX)
     */
    public function getBankAccounts(Request $request): \Illuminate\Http\JsonResponse
    {
        try {
            $bankAccounts = 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,
                        'currency' => $account->currency,
                    ];
                })->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(Request $request): \Illuminate\Http\JsonResponse
    {
        try {
            $type = $request->get('type', 'all'); // 'manual', 'esignature', or 'all'
            $query = Signature::where('is_active', true);

            if ($type !== 'all') {
                $query->where('type', $type);
            }

            $signatures = $query->orderBy('name', 'asc')->get();

            return response()->json([
                'success' => true,
                'signatures' => $signatures->map(function ($signature) {
                    $url = '';
                    if ($signature->content && \Illuminate\Support\Facades\Storage::disk('public')->exists($signature->content)) {
                        $url = \Illuminate\Support\Facades\Storage::url($signature->content);
                    }

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

    /**
     * API: Get products for dropdown (AJAX)
     */
    public function getProducts(Request $request): \Illuminate\Http\JsonResponse
    {
        try {
            $query = \App\Models\Product::with(['unit']);

            $search = $request->get('search', '');
            if (! empty($search)) {
                $query->where(function ($q) use ($search) {
                    $q->where('name', 'like', "%{$search}%")
                        ->orWhere('code', '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 ?? '',
                        'unit' => $product->unit ? $product->unit->short_name : '',
                        'selling_price' => $product->selling_price ?? 0,
                        'purchase_price' => $product->purchase_price ?? 0,
                    ];
                })->toArray(),
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error fetching products: '.$e->getMessage(),
                'products' => [],
            ], 500);
        }
    }

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

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

    /**
     * Show the form for editing the specified resource.
     */
    public function edit(Purchase $purchase): View
    {
        $purchase->load(['items', 'supplier', 'company', 'bankAccount']);

        $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.purchases.create', [
            'purchase' => $purchase,
            'nextPurchaseNumber' => $purchase->purchase_number,
            'companySettings' => $companySettings,
            'currencies' => $currencies,
            'defaultCurrency' => $defaultCurrency,
            'defaultCurrencyModel' => $defaultCurrencyModel,
        ]);
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, Purchase $purchase): RedirectResponse
    {
        $validated = $request->validate([
            'purchase_number' => ['required', 'string', Rule::unique('purchases', 'purchase_number')->ignore($purchase->id)],
            'purchase_date' => 'required|date',
            'order_date' => 'nullable|date',
            'status' => 'required|in:new,pending,partially_paid,completed,cancelled',
            'company_id' => 'nullable|exists:companies,id',
            'supplier_id' => 'required',
            'bank_account_id' => 'nullable|exists:bank_accounts,id',
            'signature_type' => 'nullable|in:manual,esignature',
            'signature_id' => 'nullable|exists:signatures,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',
        ]);

        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;

            $supplierId = $validated['supplier_id'];
            $supplierType = $request->input('supplier_type', 'supplier');

            if ($supplierType === 'customer') {
                $customer = \App\Models\Customer::find($supplierId);
                if (! $customer) {
                    throw new \Exception('Customer not found');
                }
                $supplier = Supplier::where('name', $customer->name)
                    ->where('email', $customer->email)
                    ->first();

                if (! $supplier) {
                    $supplier = Supplier::create([
                        'name' => $customer->name,
                        'email' => $customer->email,
                        'phone' => $customer->phone,
                        'address' => $customer->address,
                        'city' => $customer->city,
                        'state' => $customer->state,
                        'zip' => $customer->zip,
                        'country' => $customer->country,
                        'image' => $customer->image,
                        'balance' => 0,
                        'mode' => 'credit',
                        'is_active' => true,
                        'created_by' => Auth::id(),
                    ]);
                }
                $supplierId = $supplier->id;
            } else {
                $supplier = Supplier::find($supplierId);
                if (! $supplier) {
                    throw new \Exception('Supplier not found');
                }
            }

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

            $purchase->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;

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

            DB::commit();

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

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

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(Request $request, Purchase $purchase): RedirectResponse|\Illuminate\Http\JsonResponse
    {
        $number = $purchase->purchase_number;
        $purchase->delete();

        if ($request->wantsJson() || $request->expectsJson()) {
            return response()->json(['success' => true, 'message' => 'Purchase deleted successfully.']);
        }

        return redirect()->route('admin.purchases.index')
            ->with('success', 'Purchase '.$number.' deleted successfully.');
    }
}
