<?php

namespace App\Http\Controllers\Admin;

use App\Core\Repositories\CustomerRepository;
use App\Core\Services\Customer\CustomerService;
use App\Http\Controllers\Controller;
use App\Services\ReminderService;
use Dompdf\Dompdf;
use Dompdf\Options;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\View\View;

class CustomerController extends Controller
{
    public function __construct(
        private CustomerRepository $customerRepository,
        private CustomerService $customerService,
        private ReminderService $reminderService
    ) {}

    /**
     * Display a listing of the resource.
     */
    public function index(Request $request): View|JsonResponse
    {
        $filters = [
            'search' => $request->get('search'),
            'is_active' => $request->get('is_active'),
        ];

        $customers = $this->customerRepository->getPaginated(15, $filters);

        // If AJAX request, return JSON
        if ($request->ajax()) {
            return response()->json([
                'html' => view('admin.customers.partials.table', ['customers' => $customers])->render(),
                'pagination' => view('admin.customers.partials.pagination', ['customers' => $customers])->render(),
            ]);
        }

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

    /**
     * Export customers to CSV or PDF
     */
    public function export(Request $request)
    {
        try {
            $filters = [
                'search' => $request->get('search'),
                'is_active' => $request->get('is_active'),
            ];

            // Get all customers (not paginated) for export
            $customers = $this->customerRepository->getAllWithFilters($filters);
            $format = $request->get('format', 'csv'); // Default to CSV

            if ($format === 'pdf') {
                return $this->exportPdf($customers, $filters);
            }

            return $this->exportCsv($customers);
        } catch (\Exception $e) {
            \Log::error('Export error: '.$e->getMessage());

            return redirect()
                ->route('admin.customers.index')
                ->with('error', 'Failed to export: '.$e->getMessage());
        }
    }

    /**
     * Export customers to CSV
     */
    private function exportCsv($customers)
    {
        try {
            $filename = 'customers_'.date('Y-m-d_His').'.csv';

            return response()->streamDownload(function () use ($customers) {
                $file = fopen('php://output', 'w');

                // Add BOM for UTF-8
                fprintf($file, chr(0xEF).chr(0xBB).chr(0xBF));

                // Add CSV headers
                fputcsv($file, [
                    'Name',
                    'Email',
                    'Phone',
                    'Company',
                    'Address',
                    'City',
                    'State',
                    'Zip',
                    'Country',
                    'Status',
                    'Total Invoices',
                    'Outstanding Balance',
                    'Created At',
                ]);

                // Add customer data
                foreach ($customers as $customer) {
                    $balance = $customer->invoices ? $customer->invoices->sum('balance') : 0;
                    $invoiceCount = $customer->invoices ? $customer->invoices->count() : 0;

                    fputcsv($file, [
                        $customer->name,
                        $customer->email ?? '',
                        $customer->phone ?? '',
                        $customer->company ?? '',
                        $customer->address ?? '',
                        $customer->city ?? '',
                        $customer->state ?? '',
                        $customer->zip ?? '',
                        $customer->country ?? '',
                        $customer->is_active ? 'Active' : 'Inactive',
                        $invoiceCount,
                        number_format($balance, 2),
                        $customer->created_at->format('Y-m-d H:i:s'),
                    ]);
                }

                fclose($file);
            }, $filename, [
                'Content-Type' => 'text/csv; charset=UTF-8',
                'Content-Disposition' => 'attachment; filename="'.$filename.'"',
                'Pragma' => 'no-cache',
                'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0',
                'Expires' => '0',
            ]);
        } catch (\Exception $e) {
            \Log::error('CSV Export error: '.$e->getMessage().' | Trace: '.$e->getTraceAsString());
            if (request()->expectsJson() || request()->ajax()) {
                return response()->json(['error' => 'Failed to export CSV: '.$e->getMessage()], 500);
            }

            return redirect()
                ->route('admin.customers.index')
                ->with('error', 'Failed to export CSV: '.$e->getMessage());
        }
    }

    /**
     * Export customers to PDF
     */
    private function exportPdf($customers, $filters)
    {
        try {
            $options = new Options;
            $options->set('isHtml5ParserEnabled', true);
            $options->set('isRemoteEnabled', true);
            $options->set('defaultFont', 'DejaVu Sans');
            $options->set('chroot', public_path());

            $dompdf = new Dompdf($options);

            $html = view('admin.customers.export-pdf', [
                'customers' => $customers,
                'filters' => $filters,
            ])->render();

            $dompdf->loadHtml($html);
            $dompdf->setPaper('A4', 'landscape');
            $dompdf->render();

            $filename = 'customers_'.date('Y-m-d_His').'.pdf';

            return response($dompdf->output(), 200, [
                'Content-Type' => 'application/pdf',
                'Content-Disposition' => 'attachment; filename="'.$filename.'"',
            ]);
        } catch (\Exception $e) {
            \Log::error('PDF Export error: '.$e->getMessage().' | Trace: '.$e->getTraceAsString());
            if (request()->expectsJson() || request()->ajax()) {
                return response()->json(['error' => 'Failed to export PDF: '.$e->getMessage()], 500);
            }

            return redirect()
                ->route('admin.customers.index')
                ->with('error', 'Failed to export PDF: '.$e->getMessage());
        }
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create(): View
    {
        return view('admin.customers.create');
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:customers,email|max:255',
            'phone' => 'nullable|string|max:255',
            'company' => 'nullable|string|max:255',
            'address' => 'nullable|string',
            'city' => 'nullable|string|max:255',
            'state' => 'nullable|string|max:255',
            'zip' => 'nullable|string|max:255',
            'country' => 'nullable|string|max:255',
            'notes' => 'nullable|string',
            'image' => 'nullable|image|mimes:jpeg,png,jpg|max:5120',
        ]);

        // Build address from billing address fields if provided
        if ($request->filled('billing_address_line1')) {
            $addressParts = [];
            if ($request->filled('billing_address_line1')) {
                $addressParts[] = $request->billing_address_line1;
            }
            if ($request->filled('billing_address_line2')) {
                $addressParts[] = $request->billing_address_line2;
            }
            $validated['address'] = implode(', ', $addressParts);
            $validated['city'] = $request->billing_city ?? null;
            $validated['state'] = $request->billing_state ?? null;
            $validated['zip'] = $request->billing_pincode ?? null;
            $validated['country'] = $request->billing_country ?? null;
        }

        // Handle image upload
        if ($request->hasFile('image')) {
            $imagePath = $request->file('image')->store('customers', 'public');
            $validated['image'] = $imagePath;
        }

        try {
            $customer = $this->customerService->create($validated);

            try {
                $this->reminderService->sendCustomerWelcome($customer);
            } catch (\Throwable) {
            }

            return redirect()
                ->route('admin.customers.index')
                ->with('success', 'Customer created successfully.');
        } catch (\Exception $e) {
            return redirect()
                ->back()
                ->withInput()
                ->withErrors(['error' => 'Failed to create customer: '.$e->getMessage()]);
        }
    }

    /**
     * Display the specified resource.
     */
    public function show(string $id): View
    {
        $customer = $this->customerRepository->getById($id);

        if (! $customer) {
            abort(404, 'Customer not found');
        }

        // Load relationships
        $customer->load(['invoices', 'estimates', 'payments']);

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

    /**
     * Show the form for editing the specified resource.
     */
    public function edit(string $id): View
    {
        $customer = $this->customerRepository->getById($id);

        if (! $customer) {
            abort(404, 'Customer not found');
        }

        return view('admin.customers.edit', [
            'customer' => $customer,
        ]);
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, string $id): RedirectResponse
    {
        $customer = $this->customerRepository->getById($id);

        if (! $customer) {
            abort(404, 'Customer not found');
        }

        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:customers,email,'.$customer->id.'|max:255',
            'phone' => 'nullable|string|max:255',
            'company' => 'nullable|string|max:255',
            'address' => 'nullable|string',
            'city' => 'nullable|string|max:255',
            'state' => 'nullable|string|max:255',
            'zip' => 'nullable|string|max:255',
            'country' => 'nullable|string|max:255',
            'notes' => 'nullable|string',
            'is_active' => 'nullable|boolean',
            'website' => 'nullable|url|max:255',
            'image' => 'nullable|image|mimes:jpeg,png,jpg|max:5120',
        ]);

        // Build address from billing address fields if provided
        if ($request->filled('billing_address_line1')) {
            $addressParts = [];
            if ($request->filled('billing_address_line1')) {
                $addressParts[] = $request->billing_address_line1;
            }
            if ($request->filled('billing_address_line2')) {
                $addressParts[] = $request->billing_address_line2;
            }
            $validated['address'] = implode(', ', $addressParts);
            $validated['city'] = $request->billing_city ?? null;
            $validated['state'] = $request->billing_state ?? null;
            $validated['zip'] = $request->billing_pincode ?? null;
            $validated['country'] = $request->billing_country ?? null;
        }

        // Handle is_active checkbox
        $validated['is_active'] = $request->has('is_active') ? true : false;

        // Handle image upload
        if ($request->hasFile('image')) {
            // Delete old image if exists
            if ($customer->image && Storage::disk('public')->exists($customer->image)) {
                Storage::disk('public')->delete($customer->image);
            }

            $imagePath = $request->file('image')->store('customers', 'public');
            $validated['image'] = $imagePath;
        }

        try {
            $this->customerService->update($customer, $validated);

            return redirect()
                ->route('admin.customers.index')
                ->with('success', 'Customer updated successfully.');
        } catch (\Exception $e) {
            return redirect()
                ->back()
                ->withInput()
                ->withErrors(['error' => 'Failed to update customer: '.$e->getMessage()]);
        }
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(string $id): RedirectResponse
    {
        $customer = $this->customerRepository->getById($id);

        if (! $customer) {
            abort(404, 'Customer not found');
        }

        try {
            // Check if customer has invoices
            if ($customer->invoices && $customer->invoices->count() > 0) {
                return redirect()
                    ->route('admin.customers.index')
                    ->with('error', 'Cannot delete customer with existing invoices. Please delete or reassign invoices first.');
            }

            $this->customerService->delete($customer);

            return redirect()
                ->route('admin.customers.index')
                ->with('success', 'Customer deleted successfully.');
        } catch (\Exception $e) {
            return redirect()
                ->route('admin.customers.index')
                ->with('error', 'Failed to delete customer: '.$e->getMessage());
        }
    }
}
