<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\BankAccount;
use App\Models\Currency;
use App\Models\Customer;
use App\Models\DeliveryChallan;
use App\Models\DeliveryChallanItem;
use App\Models\Invoice;
use App\Models\Product;
use App\Models\Signature;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\View\View;

class DeliveryChallanController extends Controller
{
    public function index(): View
    {
        $challans = DeliveryChallan::with(['customer', 'invoice', 'billFromUser', 'items'])
            ->orderBy('created_at', 'desc')
            ->paginate(15);

        return view('admin.delivery-challans.index', [
            'challans' => $challans,
        ]);
    }

    public function create(): View
    {
        // Get all invoices for pre-populating the dropdown
        $invoices = Invoice::with('customer')
            ->orderBy('created_at', 'desc')
            ->get()
            ->map(function ($invoice) {
                return [
                    'id' => $invoice->id,
                    'text' => $invoice->invoice_number.' - '.($invoice->customer->name ?? 'N/A'),
                    'invoice_number' => $invoice->invoice_number,
                    'customer' => $invoice->customer ? [
                        'id' => $invoice->customer->id,
                        'name' => $invoice->customer->name,
                    ] : null,
                ];
            });

        $defaultCurrencyCode = Currency::getDefaultCode();
        $defaultCurrencyRow = Currency::where('code', $defaultCurrencyCode)->where('is_active', true)->first();

        return view('admin.delivery-challans.create', [
            'invoices' => $invoices,
            'defaultCurrencyCode' => $defaultCurrencyCode,
            'defaultCurrencySymbol' => Currency::getSymbol($defaultCurrencyCode),
            'defaultCurrencySymbolPosition' => $defaultCurrencyRow?->symbol_position ?? 'before',
            'defaultCurrencyDecimalPlaces' => (int) ($defaultCurrencyRow?->decimal_places ?? 2),
        ]);
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'invoice_id' => 'nullable|exists:invoices,id',
            'customer_id' => 'required|exists:customers,id',
            'bill_from' => 'required|exists:users,id',
            'delivery_date' => 'required|date',
            'status' => 'required|in:pending,shipped,delivered,cancelled',
            'items' => 'required|array|min:1',
            'items.*.product' => '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|max:100',
            'items.*.unit' => 'nullable|string',
            'notes' => 'nullable|string',
            'terms' => 'nullable|string',
            'payment_method' => 'nullable|string|max:64',
            'bank_account_id' => 'nullable|exists:bank_accounts,id',
            'signature_type' => 'nullable|in:manual,esignature',
            'signature_id' => 'nullable|exists:signatures,id',
            'signature_canvas_data' => 'nullable|string',
            'signature_text' => 'nullable|string|max:255',
            'signature_font' => 'nullable|string|max:32',
        ]);

        try {
            DB::beginTransaction();

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

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

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

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

            $signatureType = $validated['signature_type'] ?? 'esignature';
            $signatureId = ($signatureType === 'esignature') ? ($validated['signature_id'] ?? null) : null;

            // Create delivery challan
            $challan = DeliveryChallan::create([
                'challan_number' => DeliveryChallan::generateChallanNumber(),
                'invoice_id' => $validated['invoice_id'] ?? null,
                'customer_id' => $validated['customer_id'],
                'bill_from_user_id' => $validated['bill_from'],
                'delivery_date' => $validated['delivery_date'],
                'status' => $validated['status'],
                'subtotal' => $subtotal,
                'tax_amount' => $totalTax,
                'discount_amount' => $totalDiscount,
                'total' => $total,
                'currency' => \App\Models\Currency::getDefaultCode(),
                'notes' => $validated['notes'] ?? null,
                'terms' => $validated['terms'] ?? null,
                'payment_method' => $validated['payment_method'] ?? null,
                'bank_account_id' => $validated['bank_account_id'] ?? null,
                'signature_id' => $signatureId,
                'signature_type' => $signatureType,
                'created_by' => Auth::id(),
            ]);

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

                DeliveryChallanItem::create([
                    'delivery_challan_id' => $challan->id,
                    'product_id' => $item['product_id'] ?? null,
                    'product_name' => $item['product'],
                    'unit' => $item['unit'] ?? null,
                    'quantity' => $item['quantity'],
                    'rate' => $item['rate'],
                    'discount' => $itemDiscount,
                    'tax' => $item['tax'] ?? 0,
                    'amount' => $itemAmount,
                ]);
            }

            DB::commit();

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

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

    public function show($id): View
    {
        return view('admin.delivery-challans.show', ['challan' => null]);
    }

    public function edit($id): View
    {
        return view('admin.delivery-challans.edit', ['challan' => null]);
    }

    public function update(Request $request, $id)
    {
        // Update logic here
        return redirect()->route('admin.delivery-challans.index')->with('success', 'Delivery challan updated successfully');
    }

    public function destroy($id)
    {
        // Delete logic here
        return redirect()->route('admin.delivery-challans.index')->with('success', 'Delivery challan deleted successfully');
    }

    // API endpoints for Select2 dropdowns
    public function getInvoices(Request $request): JsonResponse
    {
        try {
            $query = Invoice::with('customer');

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

            // Return all invoices (or filtered if search is provided)
            $invoices = $query->orderBy('created_at', 'desc')->get();

            return response()->json([
                'success' => true,
                'invoices' => $invoices->map(function ($invoice) {
                    return [
                        'id' => $invoice->id,
                        'text' => $invoice->invoice_number.' - '.($invoice->customer->name ?? 'N/A'),
                        'invoice_number' => $invoice->invoice_number,
                        'customer' => $invoice->customer ? [
                            'id' => $invoice->customer->id,
                            'name' => $invoice->customer->name,
                        ] : null,
                    ];
                })->toArray(),
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error fetching invoices: '.$e->getMessage(),
                'invoices' => [],
            ], 500);
        }
    }

    public function getCustomers(Request $request): JsonResponse
    {
        try {
            $query = Customer::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('company', 'like', "%{$search}%");
                });
            }

            // Return all active customers (or filtered if search is provided)
            $customers = $query->orderBy('name', 'asc')->get();

            return response()->json([
                'success' => true,
                'customers' => $customers->map(function ($customer) {
                    $imageUrl = '';
                    if ($customer->image) {
                        $imageUrl = \Illuminate\Support\Facades\Storage::disk('public')->exists($customer->image)
                            ? \Illuminate\Support\Facades\Storage::disk('public')->url($customer->image)
                            : '';
                    }

                    return [
                        'id' => $customer->id,
                        'text' => $customer->name.($customer->company ? ' - '.$customer->company : ''),
                        '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,
                    ];
                })->toArray(),
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error fetching customers: '.$e->getMessage(),
                'customers' => [],
            ], 500);
        }
    }

    public function getUsers(Request $request): JsonResponse
    {
        try {
            $query = User::with('role');

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

            // Only get admin users
            $query->whereHas('role', function ($roleQuery) {
                $roleQuery->whereIn('slug', ['admin', 'super-admin']);
            });

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

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

    public function getCompanyDetails(Request $request): JsonResponse
    {
        try {
            $companySettings = \App\Models\CompanySetting::getSettings();

            $logoUrl = '';
            if ($companySettings->company_logo) {
                $logoUrl = \Illuminate\Support\Facades\Storage::disk('public')->exists($companySettings->company_logo)
                    ? \Illuminate\Support\Facades\Storage::disk('public')->url($companySettings->company_logo)
                    : '';
            }

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

    public function getBankAccounts(Request $request): 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);
        }
    }

    public function getSignatures(Request $request): JsonResponse
    {
        try {
            $query = Signature::query();

            if (Schema::hasColumn('signatures', 'is_active')) {
                $query->where('is_active', true);
            }

            $search = $request->get('search', '');
            if (! empty($search)) {
                $query->where('name', 'like', "%{$search}%");
            }

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

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

                    return [
                        'id' => $signature->id,
                        'text' => $signature->name,
                        '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);
        }
    }

    public function getProducts(Request $request): JsonResponse
    {
        try {
            $query = Product::with(['category', 'brand', '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,
                        'text' => $product->name.' ('.($product->code ?? 'N/A').')',
                        '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);
        }
    }

    public function getInvoiceDetails($id): JsonResponse
    {
        try {
            $invoice = Invoice::with(['customer', 'items'])->findOrFail($id);

            return response()->json([
                'success' => true,
                'invoice' => [
                    'id' => $invoice->id,
                    'invoice_number' => $invoice->invoice_number,
                    'customer' => $invoice->customer ? [
                        'id' => $invoice->customer->id,
                        'name' => $invoice->customer->name,
                        'email' => $invoice->customer->email,
                        'phone' => $invoice->customer->phone,
                        'company' => $invoice->customer->company,
                        'address' => $invoice->customer->address,
                        'city' => $invoice->customer->city,
                        'state' => $invoice->customer->state,
                        'zip' => $invoice->customer->zip,
                        'country' => $invoice->customer->country,
                    ] : null,
                    'items' => $invoice->items->map(function ($item) {
                        return [
                            'description' => $item->description,
                            'quantity' => $item->quantity,
                            'unit_price' => $item->unit_price,
                            'tax_rate' => $item->tax_rate,
                            'tax_amount' => $item->tax_amount,
                            'total' => $item->total,
                        ];
                    })->toArray(),
                ],
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error fetching invoice details: '.$e->getMessage(),
                'invoice' => null,
            ], 500);
        }
    }
}
