<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\ActivityLog;
use App\Models\FeeHead;
use App\Models\FeePayment;
use App\Models\Student;
use App\Models\StudentFee;
use App\Support\SiblingDiscount;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

// E1 — Fee management: heads, invoices (student fees), collection, dues.
class FeeController extends Controller
{
    // ── Fee heads ────────────────────────────────────────────────────────
    public function heads()
    {
        return response()->json(['data' => FeeHead::orderBy('name')->get()]);
    }

    public function storeHead(Request $request)
    {
        $data = $request->validate([
            'name' => ['required', 'string'],
            'name_fa' => ['nullable', 'string'],
            'frequency' => ['required', 'in:one_time,monthly,quarterly,annual'],
            'amount' => ['required', 'numeric', 'min:0'],
        ]);

        return response()->json(['data' => FeeHead::create($data)], 201);
    }

    public function updateHead(Request $request, FeeHead $head)
    {
        $head->update($request->only(['name', 'name_fa', 'frequency', 'amount', 'is_active']));

        return response()->json(['data' => $head]);
    }

    public function destroyHead(FeeHead $head)
    {
        $head->delete();

        return response()->json(['success' => true]);
    }

    // ── Invoices ─────────────────────────────────────────────────────────
    // GET /fees/invoices?class_id=&status=&period=&student_id=
    public function invoices(Request $request)
    {
        $rows = StudentFee::with(['student:id,first_name,middle_name,last_name,admission_number,roll_number,class_id', 'student.schoolClass:id,name', 'feeHead:id,name'])
            ->when($request->query('student_id'), fn ($q, $s) => $q->where('student_id', $s))
            ->when($request->query('status'), fn ($q, $s) => $q->where('status', $s))
            ->when($request->query('period'), fn ($q, $p) => $q->where('period', $p))
            ->when($request->query('class_id'), fn ($q, $c) => $q->whereHas('student', fn ($sq) => $sq->where('class_id', $c)))
            ->orderByDesc('created_at')
            ->limit(2000)
            ->get();

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

    // POST /fees/generate { fee_head_id, period, class_id? } — bulk voucher generation.
    public function generate(Request $request)
    {
        $data = $request->validate([
            'fee_head_id' => ['required', 'exists:fee_heads,id'],
            'period' => ['required', 'string'],
            'class_id' => ['nullable', 'integer'],
            'due_date' => ['nullable', 'string'],
        ]);
        $head = FeeHead::findOrFail($data['fee_head_id']);

        $students = Student::where('status', 'active')
            ->when($data['class_id'] ?? null, fn ($q, $c) => $q->where('class_id', $c))
            ->get();

        // Sibling discounts are computed against ALL active students so families
        // that span classes still qualify even for a single-class run.
        $discounts = SiblingDiscount::forAll();

        $created = 0;
        $discounted = 0;
        DB::transaction(function () use ($students, $head, $data, $discounts, &$created, &$discounted) {
            foreach ($students as $s) {
                $exists = StudentFee::where('student_id', $s->id)
                    ->where('fee_head_id', $head->id)
                    ->where('period', $data['period'])
                    ->exists();
                if ($exists) {
                    continue;
                }
                $discount = 0;
                if (isset($discounts[$s->id])) {
                    $discount = round($head->amount * $discounts[$s->id]['percent'] / 100, 2);
                    $discounted++;
                }
                StudentFee::create([
                    'student_id' => $s->id,
                    'fee_head_id' => $head->id,
                    'title' => $head->name.' '.$data['period'],
                    'period' => $data['period'],
                    'amount' => $head->amount,
                    'discount' => $discount,
                    'status' => $discount >= $head->amount ? 'paid' : 'unpaid',
                    'due_date' => $data['due_date'] ?? null,
                ]);
                $created++;
            }
        });
        ActivityLog::record('create', 'fees', "Generated {$created} invoices for {$head->name} {$data['period']} ({$discounted} sibling-discounted)");

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

    // POST /fees/pay { student_fee_id, amount, method, note? } — collection + receipt.
    public function pay(Request $request)
    {
        $data = $request->validate([
            'student_fee_id' => ['required', 'exists:student_fees,id'],
            'amount' => ['required', 'numeric', 'min:0.01'],
            'method' => ['required', 'in:cash,bank,wallet,card'],
            'note' => ['nullable', 'string'],
        ]);

        $invoice = StudentFee::findOrFail($data['student_fee_id']);

        $payment = FeePayment::create([
            'student_fee_id' => $invoice->id,
            'student_id' => $invoice->student_id,
            'amount' => $data['amount'],
            'method' => $data['method'],
            'receipt_no' => 'RCP-'.str_pad((string) (FeePayment::max('id') + 1), 6, '0', STR_PAD_LEFT),
            'date' => now()->toDateString(),
            'received_by' => $request->user()?->name,
            'note' => $data['note'] ?? null,
        ]);
        $invoice->refreshStatus();

        // Fee income flows straight into the accounting ledger (E2).
        \App\Models\Transaction::create([
            'branch_id' => $request->header('X-Branch-Id'),
            'type' => 'income',
            'category' => 'Fees',
            'amount' => $data['amount'],
            'date' => now()->toDateString(),
            'method' => $data['method'],
            'reference' => $payment->receipt_no,
            'created_by' => $request->user()?->name,
        ]);
        ActivityLog::record('create', 'fees', "Payment {$payment->receipt_no}: {$data['amount']} ({$data['method']})", $payment);

        // WhatsApp receipt to the parent (if the automation is enabled).
        $this->sendPaymentReceipt($invoice, $payment);

        return response()->json(['data' => $payment, 'invoice' => $invoice->fresh()->load('student:id,first_name,last_name')], 201);
    }

    // GET /fees/dues — defaulter list with aging.
    public function dues(Request $request)
    {
        $rows = StudentFee::with(['student:id,first_name,middle_name,last_name,admission_number,roll_number,class_id', 'student.schoolClass:id,name', 'feeHead:id,name'])
            ->whereIn('status', ['unpaid', 'partial'])
            ->when($request->query('class_id'), fn ($q, $c) => $q->whereHas('student', fn ($sq) => $sq->where('class_id', $c)))
            ->orderBy('due_date')
            ->limit(2000)
            ->get();

        return response()->json([
            'data' => $rows,
            'total_due' => round($rows->sum(fn ($r) => $r->balance), 2),
        ]);
    }

    // GET /fees/summary — collection dashboard numbers.
    public function summary()
    {
        $today = now()->toDateString();

        return response()->json([
            'collected_today' => (float) FeePayment::where('date', $today)->sum('amount'),
            'collected_month' => (float) FeePayment::where('date', 'like', substr($today, 0, 7).'%')->sum('amount'),
            'outstanding' => (float) StudentFee::whereIn('status', ['unpaid', 'partial'])
                ->get()->sum(fn ($r) => $r->balance),
            'invoices' => StudentFee::count(),
            'paid_invoices' => StudentFee::where('status', 'paid')->count(),
        ]);
    }

    // ── Sibling / family discount policy ────────────────────────────────
    public function siblingPolicy()
    {
        return response()->json(['data' => SiblingDiscount::policy()]);
    }

    public function updateSiblingPolicy(Request $request)
    {
        $saved = SiblingDiscount::savePolicy($request->only(['enabled', 'min_children', 'mode', 'percent']));
        ActivityLog::record('update', 'fees', 'Updated sibling discount policy');

        return response()->json(['data' => $saved]);
    }

    // GET /fees/sibling-discounts — families that currently qualify + who benefits.
    public function siblingDiscounts()
    {
        $policy = SiblingDiscount::policy();
        $students = Student::where('status', 'active')->with('schoolClass:id,name')->get();
        $discounts = SiblingDiscount::forAll($students);

        // Group all students by family, then keep families with a discounted child.
        $families = [];
        foreach ($students as $s) {
            $key = SiblingDiscount::familyKey($s);
            $families[$key] ??= ['key' => $key, 'father_name' => $s->father_name, 'father_mobile' => $s->father_mobile, 'children' => []];
            $families[$key]['children'][] = [
                'id' => $s->id,
                'name' => trim($s->first_name.' '.$s->last_name),
                'photo' => $s->photo,
                'gender' => $s->gender,
                'class_name' => $s->schoolClass?->name,
                'discount_percent' => $discounts[$s->id]['percent'] ?? 0,
                'discount_reason' => $discounts[$s->id]['reason'] ?? null,
            ];
        }

        $rows = collect($families)
            ->filter(fn ($f) => collect($f['children'])->contains(fn ($c) => $c['discount_percent'] > 0))
            ->map(function ($f) {
                $f['child_count'] = count($f['children']);
                return $f;
            })
            ->sortByDesc('child_count')->values();

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

    private function sendPaymentReceipt(StudentFee $invoice, FeePayment $payment): void
    {
        try {
            $rule = \App\Models\AutomationRule::where('key', 'payment_receipt')->where('enabled', true)->with('template')->first();
            if (!$rule || !$rule->template) {
                return;
            }
            $student = Student::with('schoolClass')->find($invoice->student_id);
            if (!$student) {
                return;
            }
            $wa = app(\App\Services\WhatsAppService::class);
            $lang = \App\Models\CrmSetting::current()->default_language ?: 'fa';
            $recipient = $wa->parentRecipient($student);
            $body = $wa->render($rule->template->composed(), $recipient, [
                'fee_title' => $invoice->title,
                'amount' => number_format((float) $payment->amount),
                'receipt_no' => $payment->receipt_no,
                'date' => $payment->date,
            ]);
            $wa->queue($recipient, $body, null, 'payment_receipt', 'payment_receipt|'.$payment->id);
        } catch (\Throwable $e) {
            // Never let messaging break a payment.
        }
    }
}
