<?php
namespace Services;

use Core\Database;
use Models\FeeInvoice;
use Models\FeeStructure;
use Models\Student;

class FeeService {
    private Database $db;

    public function __construct() { $this->db = Database::getInstance(); }

    public function generateInvoices(int $termId, int $schoolId): int {
        $students = (new Student())->where('school_id=? AND status=?', [$schoolId, 'active']);
        $count = 0;
        foreach ($students as $student) {
            $classId = $this->db->fetch(
                "SELECT cl.id FROM streams st JOIN classes cl ON cl.id=st.class_id WHERE st.id=?",
                [$student['stream_id']]
            )['id'] ?? null;

            $total = $this->db->fetch(
                "SELECT SUM(amount) as t FROM fee_structures
                 WHERE term_id=? AND school_id=? AND (class_id IS NULL OR class_id=?)",
                [$termId, $schoolId, $classId]
            )['t'] ?? 0;

            if (!$total) continue;

            // Apply scholarships/discounts
            $scholarships = $this->db->fetchAll(
                "SELECT * FROM scholarships
                 WHERE student_id=? AND is_active=1 AND (term_id IS NULL OR term_id=?)",
                [$student['id'], $termId]
            );
            $discount = 0;
            foreach ($scholarships as $sc) {
                if ($sc['type'] === 'fixed') {
                    $discount += (float)$sc['value'];
                } elseif ($sc['type'] === 'percentage') {
                    $discount += ($sc['value'] / 100) * $total;
                }
            }
            $finalTotal = max(0, $total - $discount);

            $existing = $this->db->fetch(
                "SELECT id FROM fee_invoices WHERE student_id=? AND term_id=?",
                [$student['id'], $termId]
            );
            if (!$existing) {
                $this->db->insert('fee_invoices', [
                    'student_id'      => $student['id'],
                    'term_id'         => $termId,
                    'total_amount'    => $finalTotal,
                    'amount_paid'     => 0,
                    'status'          => 'unpaid',
                    'created_at'      => date('Y-m-d H:i:s'),
                    'updated_at'      => date('Y-m-d H:i:s'),
                ]);
                $count++;
            }
        }
        return $count;
    }

    public function recordPayment(int $invoiceId, float $amount, string $method, ?string $ref, int $receivedBy, ?string $notes = null, ?string $paymentDate = null): array {
        $receiptNo = 'RCP-' . strtoupper(substr(md5(uniqid()), 0, 8));
        $this->db->insert('payments', [
            'invoice_id'      => $invoiceId,
            'receipt_no'      => $receiptNo,
            'amount'          => $amount,
            'method'          => $method,
            'transaction_ref' => $ref,
            'payment_date'    => $paymentDate ?? date('Y-m-d'),
            'notes'           => $notes,
            'received_by'     => $receivedBy,
            'created_at'      => date('Y-m-d H:i:s'),
            'updated_at'      => date('Y-m-d H:i:s'),
        ]);
        (new FeeInvoice())->updatePaid($invoiceId);

        // Send SMS receipt to parent
        $this->sendPaymentSms($invoiceId, $amount, $method, $ref, $receiptNo);

        return ['receipt_no' => $receiptNo];
    }

    private function sendPaymentSms(int $invoiceId, float $amount, string $method, ?string $ref, string $receiptNo): void {
        try {
            // Get invoice + student + school info
            $invoice = $this->db->fetch(
                "SELECT fi.*, u.name AS student_name, s.assessment_no, s.school_id,
                        t.name AS term_name, ay.name AS year_name,
                        (fi.total_amount + IFNULL(fi.opening_balance,0) - fi.amount_paid) AS balance
                 FROM fee_invoices fi
                 JOIN students s ON s.id=fi.student_id
                 JOIN users u ON u.id=s.user_id
                 JOIN terms t ON t.id=fi.term_id
                 JOIN academic_years ay ON ay.id=t.academic_year_id
                 WHERE fi.id=?", [$invoiceId]
            );
            if (!$invoice) return;

            $schoolId = $invoice['school_id'];
            $school   = $this->db->fetch("SELECT name FROM schools WHERE id=?", [$schoolId]);

            // Get parent phone numbers
            $parents = $this->db->fetchAll(
                "SELECT pu.phone, pu.name AS parent_name FROM parent_student ps
                 JOIN parents p ON p.id=ps.parent_id
                 JOIN users pu ON pu.id=p.user_id
                 JOIN students s ON s.id=ps.student_id
                 JOIN fee_invoices fi ON fi.student_id=s.id
                 WHERE fi.id=? AND pu.phone IS NOT NULL", [$invoiceId]
            );
            if (empty($parents)) return;

            $balance    = (float)$invoice['balance'];
            $methodName = strtoupper($method);
            $refText    = $ref ? " Ref: {$ref}." : '';
            $balText    = $balance > 0
                ? 'Balance: KES '.number_format($balance, 2).'.'
                : 'Account FULLY PAID. Thank you!';

            $sms = new SmsService($schoolId);
            foreach ($parents as $par) {
                $firstName = explode(' ', $par['parent_name'])[0];
                $message   = "Dear {$firstName}, payment of KES ".number_format($amount, 2)
                           . " received for {$invoice['student_name']} ({$invoice['year_name']} {$invoice['term_name']})."
                           . " Method: {$methodName}.{$refText}"
                           . " Receipt: {$receiptNo}."
                           . " {$balText}"
                           . " - {$school['name']}";
                $sms->send($par['phone'], $message, $schoolId);
            }
        } catch (\Throwable $e) {
            // Silently fail — don't break payment recording if SMS fails
        }
    }
}
