<?php
declare(strict_types=1);

namespace App\Modules\Members\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Modules\Members\Services\AutoFreezeService;

class ReportController extends Controller
{
    public function index(Request $request): Response
    {
        return $this->view('Members.Views.reports.index', []);
    }

    public function childrenAgingOut(Request $request): Response
    {
        $db = App::getInstance()->db();
        $minAge = max(0, (int) $request->get('min_age', 23));
        $maxAge = min(99, (int) $request->get('max_age', 25));

        $children = $db->select(
            "SELECT c.id, c.full_name_ar, c.date_of_birth, c.gender, c.is_frozen, c.status as child_status,
                    m.id as member_id, m.full_name_ar as parent_name, m.membership_number, m.phone_mobile,
                    TIMESTAMPDIFF(YEAR, c.date_of_birth, CURDATE()) as current_age
             FROM children c
             JOIN members m ON m.id = c.member_id AND m.is_archived = 0
             WHERE c.is_archived = 0
               AND TIMESTAMPDIFF(YEAR, c.date_of_birth, CURDATE()) BETWEEN ? AND ?
             ORDER BY c.date_of_birth ASC",
            [$minAge, $maxAge]
        );

        $nearThreshold = AutoFreezeService::getChildrenNearingThreshold();

        return $this->view('Members.Views.reports.children-aging', [
            'children'      => $children,
            'nearThreshold' => $nearThreshold,
            'minAge'        => $minAge,
            'maxAge'        => $maxAge,
        ]);
    }

    public function transfers(Request $request): Response
    {
        $db = App::getInstance()->db();
        $dateFrom = $request->get('date_from', date('Y-m-01'));
        $dateTo = $request->get('date_to', date('Y-m-d'));
        $type = $request->get('type', '');

        $where = "tr.status = 'completed' AND tr.completed_at BETWEEN ? AND ?";
        $params = [$dateFrom . ' 00:00:00', $dateTo . ' 23:59:59'];

        if ($type !== '') {
            $where .= " AND tr.transfer_type = ?";
            $params[] = $type;
        }

        $transfers = $db->select(
            "SELECT tr.*, m.full_name_ar as source_name, m.membership_number as old_number,
                    tm.full_name_ar as target_name, tr.new_membership_number
             FROM transfer_requests tr
             LEFT JOIN members m ON m.id = tr.source_member_id
             LEFT JOIN members tm ON tm.id = tr.target_member_id
             WHERE {$where}
             ORDER BY tr.completed_at DESC",
            $params
        );

        return $this->view('Members.Views.reports.transfers', [
            'transfers' => $transfers,
            'dateFrom'  => $dateFrom,
            'dateTo'    => $dateTo,
            'type'      => $type,
        ]);
    }

    public function waivers(Request $request): Response
    {
        $db = App::getInstance()->db();
        $dateFrom = $request->get('date_from', date('Y-m-01'));
        $dateTo = $request->get('date_to', date('Y-m-d'));

        $waivers = $db->select(
            "SELECT wr.*, ms.full_name_ar as source_name, ms.membership_number,
                    mt.full_name_ar as target_name
             FROM waiver_requests wr
             LEFT JOIN members ms ON ms.id = wr.source_member_id
             LEFT JOIN members mt ON mt.id = wr.target_member_id
             WHERE wr.status = 'completed' AND wr.updated_at BETWEEN ? AND ?
             ORDER BY wr.updated_at DESC",
            [$dateFrom . ' 00:00:00', $dateTo . ' 23:59:59']
        );

        return $this->view('Members.Views.reports.waivers', [
            'waivers'  => $waivers,
            'dateFrom' => $dateFrom,
            'dateTo'   => $dateTo,
        ]);
    }

    public function subscriptionStatus(Request $request): Response
    {
        $db = App::getInstance()->db();
        $financialYear = $request->get('financial_year', self::currentFY());

        $summary = $db->select(
            "SELECT s.status, COUNT(*) as cnt, SUM(s.total_amount) as total, SUM(s.paid_amount) as paid,
                    SUM(s.fine_amount) as fines
             FROM subscriptions s
             WHERE s.financial_year = ?
             GROUP BY s.status",
            [$financialYear]
        );

        $unpaidMembers = $db->select(
            "SELECT m.id, m.full_name_ar, m.membership_number, m.phone_mobile,
                    SUM(s.total_amount - s.paid_amount) as outstanding
             FROM subscriptions s
             JOIN members m ON m.id = s.member_id AND m.is_archived = 0
             WHERE s.financial_year = ? AND s.status IN ('pending','overdue')
             GROUP BY m.id, m.full_name_ar, m.membership_number, m.phone_mobile
             ORDER BY outstanding DESC
             LIMIT 100",
            [$financialYear]
        );

        return $this->view('Members.Views.reports.subscription-status', [
            'summary'        => $summary,
            'unpaidMembers'  => $unpaidMembers,
            'financialYear'  => $financialYear,
        ]);
    }

    public function ageReport(Request $request): Response
    {
        $db = App::getInstance()->db();
        $minAge = max(0, (int) $request->get('min_age', 18));
        $maxAge = min(120, (int) $request->get('max_age', 65));

        $members = $db->select(
            "SELECT m.id, m.full_name_ar, m.membership_number, m.date_of_birth, m.gender, m.status,
                    m.phone_mobile, m.branch_id, b.name_ar as branch_name,
                    TIMESTAMPDIFF(YEAR, m.date_of_birth, CURDATE()) as age
             FROM members m
             LEFT JOIN branches b ON b.id = m.branch_id
             WHERE m.is_archived = 0
               AND m.date_of_birth IS NOT NULL
               AND TIMESTAMPDIFF(YEAR, m.date_of_birth, CURDATE()) BETWEEN ? AND ?
             ORDER BY m.date_of_birth ASC",
            [$minAge, $maxAge]
        );

        return $this->view('Members.Views.reports.age-report', [
            'members' => $members,
            'minAge'  => $minAge,
            'maxAge'  => $maxAge,
            'total'   => count($members),
        ]);
    }

    public function unpaidDebts(Request $request): Response
    {
        $db = App::getInstance()->db();

        $unpaidFines = $db->select(
            "SELECT f.id, f.amount, f.paid_amount, f.penalty_type, f.created_at,
                    m.id as member_id, m.full_name_ar, m.membership_number, m.phone_mobile
             FROM fines f
             JOIN members m ON m.id = f.member_id AND m.is_archived = 0
             WHERE f.status = 'imposed' AND f.penalty_type = 'fine' AND (f.amount - f.paid_amount) > 0
             ORDER BY f.created_at DESC"
        );

        $unpaidInstallments = $db->select(
            "SELECT ip.id as plan_id, ip.total_with_interest, ip.member_id,
                    m.full_name_ar, m.membership_number, m.phone_mobile,
                    COUNT(isi.id) as overdue_items,
                    SUM(isi.amount) as overdue_amount
             FROM installment_plans ip
             JOIN members m ON m.id = ip.member_id AND m.is_archived = 0
             JOIN installment_schedule isi ON isi.installment_plan_id = ip.id AND isi.status IN ('pending','overdue') AND isi.due_date < CURDATE()
             WHERE ip.status = 'active'
             GROUP BY ip.id, ip.total_with_interest, ip.member_id, m.full_name_ar, m.membership_number, m.phone_mobile
             ORDER BY overdue_amount DESC"
        );

        return $this->view('Members.Views.reports.unpaid-debts', [
            'unpaidFines'        => $unpaidFines,
            'unpaidInstallments' => $unpaidInstallments,
        ]);
    }

    private static function currentFY(): string
    {
        $month = (int) date('n');
        $year = (int) date('Y');
        return $month >= 7 ? $year . '/' . ($year + 1) : ($year - 1) . '/' . $year;
    }
}
