<?php

namespace App\Http\Controllers\Admin;

use App\Core\Repositories\InvoiceRepository;
use App\Http\Controllers\Controller;
use App\Models\CreditNote;
use App\Models\Currency;
use App\Models\Invoice;
use Dompdf\Dompdf;
use Dompdf\Options;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
use Symfony\Component\HttpFoundation\StreamedResponse;

class TransactionReportController extends Controller
{
    public function __construct(
        private InvoiceRepository $invoiceRepository
    ) {}

    public function sales(Request $request): View
    {
        $dateFrom = $request->get('date_from', now()->startOfMonth()->format('Y-m-d'));
        $dateTo = $request->get('date_to', now()->format('Y-m-d'));

        // Calculate stats
        $stats = $this->getSalesStats($dateFrom, $dateTo);

        return view('admin.reports.transactions.sales', [
            'totalSales' => $stats['totalSales'],
            'totalInvoices' => $stats['totalInvoices'],
            'paidInvoices' => $stats['paidInvoices'],
            'unpaidInvoices' => $stats['unpaidInvoices'],
            'dateFrom' => $dateFrom,
            'dateTo' => $dateTo,
        ]);
    }

    /**
     * API endpoint to fetch sales data in real-time
     */
    public function getSalesData(Request $request): JsonResponse
    {
        $dateFrom = $request->get('date_from', now()->startOfMonth()->format('Y-m-d'));
        $dateTo = $request->get('date_to', now()->format('Y-m-d'));
        $status = $request->get('status');
        $search = $request->get('search');

        $query = Invoice::with('customer')
            ->whereBetween('issue_date', [$dateFrom, $dateTo]);

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

        if ($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}%");
                    });
            });
        }

        $invoices = $query->orderBy('issue_date', 'desc')
            ->orderBy('created_at', 'desc')
            ->get()
            ->map(function ($invoice) {
                return [
                    'id' => $invoice->id,
                    'invoice_number' => $invoice->invoice_number,
                    'customer_name' => $invoice->customer->name ?? 'N/A',
                    'customer_email' => $invoice->customer->email ?? '',
                    'issue_date' => $invoice->issue_date->format('M d, Y'),
                    'amount' => number_format($invoice->total, 2),
                    'status' => $invoice->status,
                    'status_label' => ucfirst($invoice->status),
                ];
            });

        // Get updated stats
        $stats = $this->getSalesStats($dateFrom, $dateTo, $status, $search);

        return response()->json([
            'success' => true,
            'data' => $invoices,
            'stats' => $stats,
        ]);
    }

    /**
     * API: sales returns (credit notes) for the Sales Report → Sales Return tab.
     */
    public function getSalesReturnsData(Request $request): JsonResponse
    {
        $dateFrom = $request->get('date_from', now()->startOfMonth()->format('Y-m-d'));
        $dateTo = $request->get('date_to', now()->format('Y-m-d'));
        $status = $request->get('status');
        $search = $request->get('search');

        $query = CreditNote::with(['invoice.customer', 'customer'])
            ->whereBetween('credit_note_date', [$dateFrom, $dateTo]);

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

        if ($search) {
            $query->where(function ($q) use ($search) {
                $q->where('credit_note_number', 'like', "%{$search}%")
                    ->orWhereHas('invoice', function ($inv) use ($search) {
                        $inv->where('invoice_number', 'like', "%{$search}%")
                            ->orWhereHas('customer', function ($customerQuery) use ($search) {
                                $customerQuery->where('name', 'like', "%{$search}%")
                                    ->orWhere('email', 'like', "%{$search}%");
                            });
                    })
                    ->orWhereHas('customer', function ($customerQuery) use ($search) {
                        $customerQuery->where('name', 'like', "%{$search}%")
                            ->orWhere('email', 'like', "%{$search}%");
                    });
            });
        }

        $rows = $query->orderBy('credit_note_date', 'desc')
            ->orderBy('created_at', 'desc')
            ->get()
            ->map(function (CreditNote $note) {
                $customer = $note->customer ?? $note->invoice?->customer;

                return [
                    'id' => $note->id,
                    'credit_note_number' => $note->credit_note_number,
                    'invoice_number' => $note->invoice->invoice_number ?? '—',
                    'customer_name' => $customer->name ?? 'N/A',
                    'customer_email' => $customer->email ?? '',
                    'credit_note_date' => $note->credit_note_date->format('M d, Y'),
                    'amount' => Currency::formatAmount($note->total, $note->currency ?? null),
                    'status' => $note->status,
                    'status_label' => ucfirst($note->status),
                    'show_url' => route('admin.credit-notes.show', $note),
                ];
            });

        return response()->json([
            'success' => true,
            'data' => $rows,
        ]);
    }

    /**
     * Get sales statistics
     */
    private function getSalesStats(string $dateFrom, string $dateTo, ?string $status = null, ?string $search = null): array
    {
        $query = Invoice::whereBetween('issue_date', [$dateFrom, $dateTo]);

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

        if ($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}%");
                    });
            });
        }

        $totalSales = $query->sum('total');
        $totalInvoices = $query->count();
        $paidInvoices = (clone $query)->where('status', 'paid')->count();
        $unpaidInvoices = (clone $query)->where('status', '!=', 'paid')->count();

        return [
            'totalSales' => $totalSales,
            'totalInvoices' => $totalInvoices,
            'paidInvoices' => $paidInvoices,
            'unpaidInvoices' => $unpaidInvoices,
        ];
    }

    /**
     * Export sales data to CSV
     */
    public function exportSalesCsv(Request $request): StreamedResponse
    {
        $dateFrom = $request->get('date_from', now()->startOfMonth()->format('Y-m-d'));
        $dateTo = $request->get('date_to', now()->format('Y-m-d'));
        $status = $request->get('status');
        $search = $request->get('search');

        $query = Invoice::with('customer')
            ->whereBetween('issue_date', [$dateFrom, $dateTo]);

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

        if ($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}%");
                    });
            });
        }

        $invoices = $query->orderBy('issue_date', 'desc')->get();

        $filename = 'sales_report_'.$dateFrom.'_to_'.$dateTo.'.csv';
        $headers = [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="'.$filename.'"',
        ];

        $callback = function () use ($invoices) {
            $file = fopen('php://output', 'w');

            // CSV headers
            fputcsv($file, ['#', 'Invoice Number', 'Customer', 'Date', 'Amount', 'Status']);

            // CSV data
            foreach ($invoices as $index => $invoice) {
                fputcsv($file, [
                    $index + 1,
                    $invoice->invoice_number,
                    $invoice->customer->name ?? 'N/A',
                    $invoice->issue_date->format('Y-m-d'),
                    number_format($invoice->total, 2),
                    ucfirst($invoice->status),
                ]);
            }

            fclose($file);
        };

        return response()->stream($callback, 200, $headers);
    }

    /**
     * Export sales data to PDF
     */
    public function exportSalesPdf(Request $request)
    {
        $dateFrom = $request->get('date_from', now()->startOfMonth()->format('Y-m-d'));
        $dateTo = $request->get('date_to', now()->format('Y-m-d'));
        $status = $request->get('status');
        $search = $request->get('search');

        $query = Invoice::with('customer')
            ->whereBetween('issue_date', [$dateFrom, $dateTo]);

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

        if ($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}%");
                    });
            });
        }

        $invoices = $query->orderBy('issue_date', 'desc')->get();
        $stats = $this->getSalesStats($dateFrom, $dateTo, $status, $search);

        $html = view('admin.reports.transactions.sales-pdf', [
            'invoices' => $invoices,
            'stats' => $stats,
            'dateFrom' => $dateFrom,
            'dateTo' => $dateTo,
        ])->render();

        $options = new Options;
        $options->set('isHtml5ParserEnabled', true);
        $options->set('isRemoteEnabled', true);
        $options->set('defaultFont', 'Arial');

        $dompdf = new Dompdf($options);
        $dompdf->loadHtml($html);
        $dompdf->setPaper('A4', 'landscape');
        $dompdf->render();

        $filename = 'sales_report_'.$dateFrom.'_to_'.$dateTo.'.pdf';

        return $dompdf->stream($filename);
    }

    public function purchase(): View
    {
        return view('admin.reports.transactions.purchase');
    }

    public function quotation(): View
    {
        return view('admin.reports.transactions.quotation');
    }
}
