<?php

namespace App\Http\Controllers;

use App\Domain\Financial\Models\Invoice;
use App\Domain\Financial\Models\Payment;
use App\Domain\Participant\Models\Participant;
use App\Domain\Training\Models\Enrollment;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Gate;
use Symfony\Component\HttpFoundation\StreamedResponse;

class ExportController extends Controller
{
    public function participants(Request $request): StreamedResponse
    {
        Gate::authorize('participants.list');

        $branchId = session('active_branch_id');

        $query = Participant::with(['person', 'branch', 'primaryActivity'])
            ->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
            ->when($request->status, fn ($q, $s) => $q->where('status', $s))
            ->orderByDesc('created_at');

        return $this->streamCsv('participants', [
            'الاسم', 'الهاتف', 'البريد', 'الحالة', 'نوع العضوية', 'رقم العضوية', 'الفرع', 'النشاط', 'تاريخ التسجيل',
        ], $query, function ($p) {
            return [
                $p->person?->name_ar ?? $p->person?->name ?? '',
                $p->person?->phone ?? '',
                $p->person?->email ?? '',
                $p->status ?? '',
                $p->membership_type ?? '',
                $p->membership_id ?? '',
                $p->branch?->name_ar ?? '',
                $p->primaryActivity?->name_ar ?? '',
                $p->created_at?->format('Y-m-d'),
            ];
        });
    }

    public function payments(Request $request): StreamedResponse
    {
        Gate::authorize('invoices.list');

        $branchId = session('active_branch_id');
        $from = $request->get('from', now()->startOfMonth()->toDateString());
        $to = $request->get('to', now()->toDateString());

        $query = Payment::with(['invoice', 'creator'])
            ->where('status', 'confirmed')
            ->whereBetween('payment_date', [$from, $to])
            ->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
            ->orderByDesc('payment_date');

        return $this->streamCsv('payments', [
            'التاريخ', 'المرجع', 'المبلغ', 'الطريقة', 'رقم الفاتورة', 'بواسطة',
        ], $query, function ($p) {
            return [
                $p->payment_date?->format('Y-m-d'),
                $p->reference ?? '',
                number_format($p->amount / 100, 2),
                $p->method?->value ?? '',
                $p->invoice?->number ?? '',
                $p->creator?->name ?? '',
            ];
        });
    }

    public function invoices(Request $request): StreamedResponse
    {
        Gate::authorize('invoices.list');

        $branchId = session('active_branch_id');
        $from = $request->get('from', now()->startOfMonth()->toDateString());
        $to = $request->get('to', now()->toDateString());

        $query = Invoice::query()
            ->whereBetween('created_at', [$from, $to])
            ->when($request->status, fn ($q, $s) => $q->where('status', $s))
            ->orderByDesc('created_at');

        return $this->streamCsv('invoices', [
            'رقم الفاتورة', 'المشترك', 'الإجمالي', 'المدفوع', 'المستحق', 'الحالة', 'التاريخ', 'تاريخ الاستحقاق',
        ], $query, function ($inv) {
            return [
                $inv->number ?? '',
                $inv->contact_name ?? '',
                number_format($inv->total_amount / 100, 2),
                number_format($inv->paid_amount / 100, 2),
                number_format(($inv->total_amount - $inv->paid_amount) / 100, 2),
                $inv->status ?? '',
                $inv->created_at?->format('Y-m-d'),
                $inv->due_date?->format('Y-m-d') ?? '',
            ];
        });
    }

    public function enrollments(Request $request): StreamedResponse
    {
        Gate::authorize('enrollments.list');

        $branchId = session('active_branch_id');

        $query = Enrollment::with(['participant.person', 'group.program', 'group.branch'])
            ->when($branchId, fn ($q) => $q->whereHas('group', fn ($g) => $g->where('branch_id', $branchId)))
            ->when($request->status, fn ($q, $s) => $q->where('status', $s))
            ->orderByDesc('enrollment_date');

        return $this->streamCsv('enrollments', [
            'المشترك', 'البرنامج', 'المجموعة', 'الحالة', 'تاريخ التسجيل', 'الفرع',
        ], $query, function ($e) {
            return [
                $e->participant?->person?->name_ar ?? '',
                $e->group?->program?->name_ar ?? '',
                $e->group?->name_ar ?? '',
                $e->status ?? '',
                $e->enrollment_date?->format('Y-m-d') ?? '',
                $e->group?->branch?->name_ar ?? '',
            ];
        });
    }

    private function streamCsv(string $filename, array $headers, $query, callable $rowMapper): StreamedResponse
    {
        $date = now()->format('Y-m-d');

        return response()->streamDownload(function () use ($headers, $query, $rowMapper) {
            $handle = fopen('php://output', 'w');
            fprintf($handle, chr(0xEF) . chr(0xBB) . chr(0xBF));
            fputcsv($handle, $headers);

            $query->chunk(500, function ($records) use ($handle, $rowMapper) {
                foreach ($records as $record) {
                    fputcsv($handle, $rowMapper($record));
                }
            });

            fclose($handle);
        }, "{$filename}-{$date}.csv", [
            'Content-Type' => 'text/csv; charset=UTF-8',
        ]);
    }
}
