<?php

namespace App\Http\Controllers\Api\Finance;

use App\Http\Controllers\Api\BaseApiController;
use App\Http\Requests\Finance\FinancialReportRequest;
use App\Http\Requests\Finance\FinancialSummaryRequest;
use App\Http\Requests\Finance\FinancialUnpaidParentsRequest;
use App\Http\Resources\Finance\FinancialReportResource;
use App\Http\Resources\Finance\FinancialSummaryResource;
use App\Http\Resources\Finance\FinancialUnpaidParentResource;
use App\Services\Finance\FinancialPdfReportService;
use App\Services\Finance\FinancialReportService;
use App\Services\Finance\FinancialSchoolYearService;
use App\Services\Finance\FinancialSummaryService;
use App\Services\Finance\FinancialUnpaidParentsService;
use Illuminate\Http\JsonResponse;
use Symfony\Component\HttpFoundation\StreamedResponse;

class FinancialController extends BaseApiController
{
    public function __construct(
        private FinancialReportService $reportService,
        private FinancialSummaryService $summaryService,
        private FinancialUnpaidParentsService $unpaidParentsService,
        private FinancialSchoolYearService $schoolYears,
        private FinancialPdfReportService $pdfService
    ) {
        parent::__construct();
    }

    public function report(FinancialReportRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $report = $this->reportService->getReport(
            $payload['date_from'] ?? null,
            $payload['date_to'] ?? null,
            $payload['school_year'] ?? null
        );

        return response()->json([
            'ok' => true,
            'report' => new FinancialReportResource($report),
        ]);
    }

    public function summary(FinancialSummaryRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $summary = $this->summaryService->getSummary(
            $payload['date_from'] ?? null,
            $payload['date_to'] ?? null,
            $payload['school_year'] ?? null
        );

        $schoolYears = $this->schoolYears->listYears($summary['schoolYear'] ?? null);

        return response()->json([
            'ok' => true,
            'summary' => new FinancialSummaryResource($summary),
            'schoolYears' => $schoolYears,
        ]);
    }

    public function unpaidParents(FinancialUnpaidParentsRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $data = $this->unpaidParentsService->getUnpaidParents($payload['school_year'] ?? null);

        return response()->json([
            'ok' => true,
            'schoolYear' => $data['schoolYear'] ?? null,
            'schoolYears' => $data['schoolYears'] ?? [],
            'results' => FinancialUnpaidParentResource::collection($data['results'] ?? []),
        ]);
    }

    public function downloadCsv(FinancialReportRequest $request): StreamedResponse
    {
        $payload = $request->validated();
        $report = $this->reportService->getReport(
            $payload['date_from'] ?? null,
            $payload['date_to'] ?? null,
            $payload['school_year'] ?? null
        );

        $paymentsMap = [];
        foreach ($report['payments'] as $payment) {
            $invoiceId = (int) ($payment['invoice_id'] ?? 0);
            $paymentsMap[$invoiceId] = (float) ($payment['paid_amount'] ?? 0);
        }

        $refundsMap = [];
        foreach ($report['refunds'] as $refund) {
            $invoiceId = (int) ($refund['invoice_id'] ?? 0);
            $refundsMap[$invoiceId] = (float) ($refund['total_refunded'] ?? 0);
        }

        $discountsMap = [];
        foreach ($report['discounts'] as $discount) {
            $invoiceId = (int) ($discount['invoice_id'] ?? 0);
            $discountsMap[$invoiceId] = (float) ($discount['discount_amount'] ?? 0);
        }

        $breakdown = $report['paymentBreakdown'] ?? [];

        $filename = 'financial_report_' . date('Ymd_His') . '.csv';

        return response()->streamDownload(function () use ($report, $paymentsMap, $refundsMap, $discountsMap, $breakdown) {
            $out = fopen('php://output', 'w');

            fputcsv($out, ['Invoice #', 'Parent', 'School Year', 'Total', 'Paid', 'Cash', 'Credit', 'Check', 'Balance', 'Refund', 'Discount', 'Status']);
            $sumTotal = 0.0;
            $sumPaid = 0.0;
            $sumCash = 0.0;
            $sumCredit = 0.0;
            $sumCheck = 0.0;
            $sumBalance = 0.0;
            $sumRefund = 0.0;
            $sumDiscount = 0.0;

            foreach ($report['invoices'] as $inv) {
                $invoiceId = (int) ($inv['id'] ?? 0);
                $paid = (float) ($paymentsMap[$invoiceId] ?? 0);
                $bd = $breakdown[$invoiceId] ?? [];
                $cash = (float) ($bd['cash'] ?? 0);
                $credit = (float) ($bd['credit'] ?? 0);
                $check = (float) ($bd['check'] ?? 0);
                $refunded = (float) ($refundsMap[$invoiceId] ?? 0);
                $discount = (float) ($discountsMap[$invoiceId] ?? 0);
                $total = (float) ($inv['total_amount'] ?? 0);
                $balance = $total - $paid - $discount - $refunded;
                if ($balance < 0) {
                    $balance = 0.0;
                }
                $status = $balance === 0.0 ? 'Paid' : 'Unpaid';

                fputcsv($out, [
                    $inv['invoice_number'] ?? '',
                    $inv['parent_name'] ?? '',
                    $inv['school_year'] ?? '',
                    $total,
                    $paid,
                    $cash,
                    $credit,
                    $check,
                    $balance,
                    $refunded,
                    $discount,
                    $status,
                ]);

                $sumTotal += $total;
                $sumPaid += $paid;
                $sumCash += $cash;
                $sumCredit += $credit;
                $sumCheck += $check;
                $sumBalance += $balance;
                $sumRefund += $refunded;
                $sumDiscount += $discount;
            }

            fputcsv($out, [
                'TOTALS',
                '',
                '',
                $sumTotal,
                $sumPaid,
                $sumCash,
                $sumCredit,
                $sumCheck,
                $sumBalance,
                $sumRefund,
                $sumDiscount,
                '',
            ]);

            fputcsv($out, []);
            fputcsv($out, ['Expenses Summary']);
            fputcsv($out, ['Category', 'Total Amount']);
            foreach ($report['expenses'] as $exp) {
                fputcsv($out, [
                    $exp['category'] ?? '',
                    $exp['total_amount'] ?? 0,
                ]);
            }

            fputcsv($out, []);
            fputcsv($out, ['Reimbursements Summary']);
            fputcsv($out, ['Status', 'Total Amount']);
            foreach ($report['reimbursements'] as $row) {
                fputcsv($out, [
                    $row['status'] ?? '',
                    $row['total_amount'] ?? 0,
                ]);
            }

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

    public function downloadPdf(FinancialReportRequest $request): StreamedResponse
    {
        $payload = $request->validated();
        $summary = $this->summaryService->getSummary(
            $payload['date_from'] ?? null,
            $payload['date_to'] ?? null,
            $payload['school_year'] ?? null
        );

        $pdfBytes = $this->pdfService->buildPdf($summary);
        $schoolYear = $summary['schoolYear'] ?? 'report';

        return response()->streamDownload(function () use ($pdfBytes) {
            echo $pdfBytes;
        }, 'Financial_Report_' . $schoolYear . '.pdf', ['Content-Type' => 'application/pdf']);
    }
}
