<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\ClientInvoice;
use App\Models\Client;
use App\Models\Currency;

class OutstandingFeesController extends Controller
{
    private function binaryPdfResponse($pdf, string $filename)
    {
        while (ob_get_level() > 0) {
            ob_end_clean();
        }

        return response($pdf->output(), 200, [
            'Content-Type' => 'application/pdf',
            'Content-Disposition' => 'attachment; filename="' . $filename . '"',
            'Cache-Control' => 'private, max-age=0, must-revalidate',
            'Pragma' => 'public',
        ]);
    }

    public function index(Request $request)
    {
        return view('modules.reports.outstanding-fees', $this->buildReportData($request));
    }

    public function downloadPdf(Request $request)
    {
        $reportData = $this->buildReportData($request);
        $pdf = \PDF::loadView('modules.reports.outstanding-fees-pdf', $reportData);

        return $this->binaryPdfResponse($pdf, 'outstanding_fees_' . $reportData['dateFrom'] . '_to_' . $reportData['dateTo'] . '.pdf');
    }

    public function exportExcel(Request $request)
    {
        $reportData = $this->buildReportData($request);
        $invoices = $reportData['invoices'];
        $filename = 'outstanding_fees_' . $reportData['dateFrom'] . '_to_' . $reportData['dateTo'] . '.csv';

        return response()->streamDownload(function () use ($invoices) {
            $out = fopen('php://output', 'w');
            fputcsv($out, ['Client Name', 'Invoice #', 'Invoice Date', 'Due Date', 'Total Amount', 'Paid Amount', 'Balance Due', 'Status', 'Days Overdue', 'Currency']);

            foreach ($invoices as $invoice) {
                fputcsv($out, [
                    $invoice->customer->full_name ?? 'N/A',
                    $invoice->invoice_number,
                    optional($invoice->invoice_date)->format('Y-m-d'),
                    optional($invoice->due_date_computed)->format('Y-m-d'),
                    number_format((float) $invoice->total, 2, '.', ''),
                    number_format((float) ($invoice->paid_amount ?? 0), 2, '.', ''),
                    number_format((float) ($invoice->balance_due ?? 0), 2, '.', ''),
                    $invoice->status_label ?? 'unpaid',
                    (int) ($invoice->days_overdue ?? 0),
                    $invoice->currency->currency_code ?? 'N/A',
                ]);
            }

            fclose($out);
        }, $filename, [
            'Content-Type' => 'text/csv',
        ]);
    }

    private function buildReportData(Request $request): array
    {
        $clients = Client::orderBy('first_name')->orderBy('last_name')->get();
        $currencies = Currency::all();

        $clientId = $request->query('client_id');
        $dateFrom = $request->query('date_from', now()->startOfMonth()->format('Y-m-d'));
        $dateTo = $request->query('date_to', now()->format('Y-m-d'));
        $currencyId = $request->query('curr');

        // Outstanding Fees uses client_invoices only.
        $invoiceQuery = ClientInvoice::with(['customer', 'currency'])
            ->where('status', '!=', 'draft')
            ->where('status', '!=', 'paid');

        if (!empty($clientId) && $clientId !== 'all') {
            $invoiceQuery->where('client_id', $clientId);
        }
        if (!empty($dateFrom)) {
            $invoiceQuery->whereDate('invoice_date', '>=', $dateFrom);
        }
        if (!empty($dateTo)) {
            $invoiceQuery->whereDate('invoice_date', '<=', $dateTo);
        }
        if (!empty($currencyId)) {
            $invoiceQuery->where('currency_id', $currencyId);
        }

        $invoices = $invoiceQuery->orderBy('invoice_date', 'desc')->get()->map(function ($invoice) {
            $dueDate = \Carbon\Carbon::parse($invoice->invoice_date)->addDays(30);
            $isOverdue = $dueDate->isPast();
            $status = strtolower((string) $invoice->status) === 'overdue' || $isOverdue ? 'overdue' : 'unpaid';

            $invoice->paid_amount = 0.0;
            $invoice->balance_due = (float) $invoice->total;
            $invoice->status_label = $status;
            $invoice->due_date_computed = $dueDate;
            $invoice->days_overdue = $isOverdue ? now()->diffInDays($dueDate) : 0;

            return $invoice;
        });

        $overdueInvoices = $invoices->where('days_overdue', '>', 0);
        $metrics = [
            'totalOutstanding' => $invoices->sum('balance_due'),
            'overdueAmount' => $overdueInvoices->sum('balance_due'),
            'totalInvoices' => $invoices->count(),
            'avgDaysOverdue' => round($overdueInvoices->avg('days_overdue') ?? 0),
        ];

        return compact(
            'invoices',
            'metrics',
            'clients',
            'currencies',
            'clientId',
            'dateFrom',
            'dateTo',
            'currencyId'
        );
    }
}
