<?php

class SubscriptionApiController extends Controller
{
    // ══════════════════════════════════════════════════
    //  SUBSCRIPTION DATATABLE
    // ══════════════════════════════════════════════════
    public function datatable(Request $request): void
    {
        $db = $this->db();
        $draw   = (int) $request->get('draw', 1);
        $start  = (int) $request->get('start', 0);
        $length = (int) $request->get('length', 25);
        $search = $request->get('search')['value'] ?? '';

        $statusFilter = $request->get('status', '');
        $periodFilter = $request->get('period_id', '');
        $typeFilter   = $request->get('type_id', '');

        $where = "1=1";
        $params = [];

        if ($statusFilter !== '') {
            $where .= " AND ms.status = ?";
            $params[] = $statusFilter;
        }
        if ($periodFilter !== '') {
            $where .= " AND ms.subscription_period_id = ?";
            $params[] = $periodFilter;
        }
        if ($typeFilter !== '') {
            $where .= " AND ms.membership_type_id = ?";
            $params[] = $typeFilter;
        }
        if ($search !== '') {
            $where .= " AND (m.membership_number LIKE ? OR m.full_name_en LIKE ? OR m.full_name_ar LIKE ? OR m.primary_phone LIKE ?)";
            $s = "%{$search}%";
            $params = array_merge($params, [$s, $s, $s, $s]);
        }

        $totalRecords = (int) $db->fetchColumn("SELECT COUNT(*) FROM member_subscriptions ms JOIN members m ON ms.member_id = m.id");
        $filteredRecords = (int) $db->fetchColumn(
            "SELECT COUNT(*) FROM member_subscriptions ms JOIN members m ON ms.member_id = m.id WHERE {$where}",
            $params
        );

        $orderCol = (int) ($request->get('order')[0]['column'] ?? 0);
        $orderDir = strtoupper($request->get('order')[0]['dir'] ?? 'DESC') === 'ASC' ? 'ASC' : 'DESC';
        $columns  = ['ms.id', 'm.membership_number', 'm.full_name_en', 'mt.name_en', 'sp.name_en', 'ms.start_date', 'ms.end_date', 'ms.net_amount', 'ms.paid_amount', 'ms.status'];
        $orderBy  = ($columns[$orderCol] ?? 'ms.id') . ' ' . $orderDir;

        $rows = $db->fetchAll(
            "SELECT ms.id, ms.start_date, ms.end_date, ms.net_amount, ms.paid_amount, ms.balance_due, ms.status,
                    m.membership_number, m.full_name_en AS member_name, m.id AS member_id,
                    mt.name_en AS type_name, sp.name_en AS period_name
             FROM member_subscriptions ms
             JOIN members m ON ms.member_id = m.id
             JOIN membership_types mt ON ms.membership_type_id = mt.id
             JOIN subscription_periods sp ON ms.subscription_period_id = sp.id
             WHERE {$where}
             ORDER BY {$orderBy}
             LIMIT {$length} OFFSET {$start}",
            $params
        );

        $data = [];
        foreach ($rows as $r) {
            $actions = '<a href="/subscriptions/' . $r['id'] . '" class="btn btn-sm btn-outline-primary" data-bs-toggle="tooltip" title="View"><i class="fas fa-eye"></i></a>';
            $data[] = [
                'id'              => $r['id'],
                'membership_number' => e($r['membership_number']),
                'member_name'     => e($r['member_name']),
                'type_name'       => e($r['type_name']),
                'period_name'     => e($r['period_name']),
                'start_date'      => format_date($r['start_date']),
                'end_date'        => format_date($r['end_date']),
                'net_amount'      => format_money($r['net_amount']),
                'paid_amount'     => format_money($r['paid_amount']),
                'status'          => status_badge($r['status']),
                'actions'         => $actions,
            ];
        }

        $this->json([
            'draw'            => $draw,
            'recordsTotal'    => $totalRecords,
            'recordsFiltered' => $filteredRecords,
            'data'            => $data,
        ]);
    }

    // ══════════════════════════════════════════════════
    //  EXPIRING DATATABLE
    // ══════════════════════════════════════════════════
    public function expiringDatatable(Request $request): void
    {
        $db = $this->db();
        $draw   = (int) $request->get('draw', 1);
        $start  = (int) $request->get('start', 0);
        $length = (int) $request->get('length', 25);
        $days   = (int) $request->get('days', 30);

        if ($days < 1 || $days > 365) $days = 30;

        $where  = "ms.status = 'active' AND ms.end_date BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL ? DAY)";
        $params = [$days];

        $search = $request->get('search')['value'] ?? '';
        if ($search !== '') {
            $where .= " AND (m.membership_number LIKE ? OR m.full_name_en LIKE ?)";
            $s = "%{$search}%";
            $params[] = $s;
            $params[] = $s;
        }

        $total = (int) $db->fetchColumn(
            "SELECT COUNT(*) FROM member_subscriptions ms JOIN members m ON ms.member_id = m.id WHERE {$where}",
            $params
        );

        $rows = $db->fetchAll(
            "SELECT ms.id, ms.start_date, ms.end_date, ms.net_amount, ms.status,
                    DATEDIFF(ms.end_date, CURDATE()) AS days_remaining,
                    m.membership_number, m.full_name_en AS member_name, m.primary_phone, m.id AS member_id,
                    mt.name_en AS type_name
             FROM member_subscriptions ms
             JOIN members m ON ms.member_id = m.id
             JOIN membership_types mt ON ms.membership_type_id = mt.id
             WHERE {$where}
             ORDER BY ms.end_date ASC
             LIMIT {$length} OFFSET {$start}",
            $params
        );

        $data = [];
        foreach ($rows as $r) {
            $badge = $r['days_remaining'] <= 7 ? '<span class="badge bg-danger">' . $r['days_remaining'] . ' days</span>'
                : ($r['days_remaining'] <= 14 ? '<span class="badge bg-warning">' . $r['days_remaining'] . ' days</span>'
                : '<span class="badge bg-info">' . $r['days_remaining'] . ' days</span>');

            $data[] = [
                'membership_number' => e($r['membership_number']),
                'member_name'       => e($r['member_name']),
                'phone'             => e($r['primary_phone'] ?? ''),
                'type_name'         => e($r['type_name']),
                'end_date'          => format_date($r['end_date']),
                'days_remaining'    => $badge,
                'actions'           => '<a href="/subscriptions/create?member_id=' . $r['member_id'] . '" class="btn btn-sm btn-success"><i class="fas fa-redo me-1"></i>Renew</a>',
            ];
        }

        $this->json([
            'draw'            => $draw,
            'recordsTotal'    => $total,
            'recordsFiltered' => $total,
            'data'            => $data,
        ]);
    }

    // ══════════════════════════════════════════════════
    //  CALCULATE FEE
    // ══════════════════════════════════════════════════
    public function calculateFee(Request $request): void
    {
        $db = $this->db();
        $memberId = (int) $request->get('member_id');
        $periodId = (int) $request->get('period_id');

        if (!$memberId || !$periodId) {
            $this->json(['success' => false, 'message' => 'Missing parameters'], 400);
            return;
        }

        $member = $db->fetchOne("SELECT id, membership_type_id, status FROM members WHERE id = ? AND is_deleted = 0", [$memberId]);
        if (!$member) {
            $this->json(['success' => false, 'message' => 'Member not found'], 404);
            return;
        }

        $period = $db->fetchOne("SELECT * FROM subscription_periods WHERE id = ? AND is_active = 1", [$periodId]);
        if (!$period) {
            $this->json(['success' => false, 'message' => 'Period not found'], 404);
            return;
        }

        $fee = $db->fetchOne(
            "SELECT mtf.amount, mtf.dependent_amount, mtf.dependent_percentage
             FROM membership_type_fees mtf
             WHERE mtf.membership_type_id = ? AND mtf.fee_type_id = (SELECT id FROM fee_types WHERE fee_code = 'ANNUAL_SUB' LIMIT 1)
               AND mtf.is_active = 1
               AND mtf.effective_from <= CURDATE()
               AND (mtf.effective_to IS NULL OR mtf.effective_to >= CURDATE())
             ORDER BY mtf.effective_from DESC LIMIT 1",
            [$member['membership_type_id']]
        );

        $baseAmount = $fee ? (float) $fee['amount'] : 0;

        $depCount = (int) $db->fetchColumn(
            "SELECT COUNT(*) FROM member_dependents WHERE primary_member_id = ? AND status = 'active' AND is_deleted = 0",
            [$memberId]
        );

        $depAmount = 0;
        if ($depCount > 0 && $fee) {
            if ($fee['dependent_amount'] > 0) {
                $depAmount = (float) $fee['dependent_amount'] * $depCount;
            } elseif ($fee['dependent_percentage'] > 0) {
                $depAmount = $baseAmount * ((float) $fee['dependent_percentage'] / 100) * $depCount;
            }
        }

        // Check for late fee
        $lateFee = 0;
        $currentSub = $db->fetchOne(
            "SELECT id, end_date FROM member_subscriptions WHERE member_id = ? AND status IN ('active','expired') ORDER BY end_date DESC LIMIT 1",
            [$memberId]
        );
        if ($currentSub && $currentSub['end_date'] < date('Y-m-d')) {
            $mt = $db->fetchOne("SELECT late_fee_type, late_fee_value, late_fee_max, grace_period_days FROM membership_types WHERE id = ?", [$member['membership_type_id']]);
            if ($mt && $mt['late_fee_type'] !== 'none') {
                $endDate = strtotime($currentSub['end_date']);
                $graceDays = (int) $mt['grace_period_days'];
                $daysPastGrace = max(0, (int) ((time() - $endDate) / 86400) - $graceDays);
                if ($daysPastGrace > 0) {
                    switch ($mt['late_fee_type']) {
                        case 'fixed': $lateFee = (float) $mt['late_fee_value']; break;
                        case 'percentage': $lateFee = $baseAmount * ((float) $mt['late_fee_value'] / 100); break;
                        case 'daily_fixed': $lateFee = (float) $mt['late_fee_value'] * $daysPastGrace; break;
                        case 'daily_percentage': $lateFee = $baseAmount * ((float) $mt['late_fee_value'] / 100) * $daysPastGrace; break;
                    }
                    if ($mt['late_fee_max'] && $lateFee > (float) $mt['late_fee_max']) {
                        $lateFee = (float) $mt['late_fee_max'];
                    }
                }
            }
        }

        $this->json([
            'success'        => true,
            'base_amount'    => $baseAmount,
            'dep_count'      => $depCount,
            'dep_amount'     => round($depAmount, 2),
            'late_fee'       => round($lateFee, 2),
            'total'          => round($baseAmount + $depAmount + $lateFee, 2),
            'start_date'     => $period['start_date'],
            'end_date'       => $period['end_date'],
            'is_renewal'     => $currentSub ? true : false,
        ]);
    }

    // ══════════════════════════════════════════════════
    //  STORE SUBSCRIPTION
    // ══════════════════════════════════════════════════
    public function store(Request $request): void
    {
        if (!CSRF::validate($request->csrfToken())) {
            $this->json(['success' => false, 'message' => 'Invalid security token'], 403);
            return;
        }

        $v = new Validator($request->all(), [
            'member_id'              => 'required|integer|exists:members,id',
            'subscription_period_id' => 'required|integer|exists:subscription_periods,id',
            'amount'                 => 'required|decimal',
            'discount_amount'        => 'nullable|decimal',
            'notes'                  => 'nullable|string|max:500',
        ]);

        if ($v->fails()) {
            $this->json(['success' => false, 'errors' => $v->errors()], 422);
            return;
        }

        $data = $v->validated();
        $db = $this->db();

        $member = $db->fetchOne("SELECT id, membership_type_id, status FROM members WHERE id = ? AND is_deleted = 0", [$data['member_id']]);
        if (!$member || !in_array($member['status'], ['active', 'pending_approval'])) {
            $this->json(['success' => false, 'message' => 'Member is not eligible for subscription'], 422);
            return;
        }

        $period = $db->fetchOne("SELECT * FROM subscription_periods WHERE id = ? AND is_active = 1", [$data['subscription_period_id']]);
        if (!$period) {
            $this->json(['success' => false, 'message' => 'Invalid subscription period'], 422);
            return;
        }

        // Check duplicate
        $existing = $db->fetchOne(
            "SELECT id FROM member_subscriptions WHERE member_id = ? AND subscription_period_id = ? AND status NOT IN ('cancelled')",
            [$data['member_id'], $data['subscription_period_id']]
        );
        if ($existing) {
            $this->json(['success' => false, 'message' => 'Member already has a subscription for this period'], 422);
            return;
        }

        $discount = (float) ($data['discount_amount'] ?? 0);
        $amount   = (float) $data['amount'];
        $net      = $amount - $discount;

        $depCount = (int) $db->fetchColumn("SELECT COUNT(*) FROM member_dependents WHERE primary_member_id = ? AND status = 'active' AND is_deleted = 0", [$data['member_id']]);
        $depAmount = (float) ($request->post('dependents_amount', 0));
        $lateFee   = (float) ($request->post('late_fee', 0));

        $previousSub = $db->fetchOne(
            "SELECT id FROM member_subscriptions WHERE member_id = ? AND status IN ('active','expired') ORDER BY end_date DESC LIMIT 1",
            [$data['member_id']]
        );

        $db->beginTransaction();
        try {
            // Create invoice
            $db->execute("CALL sp_create_invoice(?, 'subscription', ?, ?, @inv_id, @inv_num)", [
                $data['member_id'], $period['end_date'], Auth::id()
            ]);
            $invResult = $db->fetchOne("SELECT @inv_id AS id, @inv_num AS num");
            $invoiceId = $invResult['id'];

            // Add line items
            $feeTypeId = $db->fetchColumn("SELECT id FROM fee_types WHERE fee_code = 'ANNUAL_SUB' LIMIT 1");
            if ($feeTypeId && $amount > 0) {
                $db->execute("CALL sp_add_invoice_item(?, ?, 'Annual Subscription', 'اشتراك سنوي', 1, ?, ?, 0)", [
                    $invoiceId, $feeTypeId, $amount, $discount
                ]);
            }
            if ($depAmount > 0) {
                $depFeeTypeId = $db->fetchColumn("SELECT id FROM fee_types WHERE fee_code = 'DEP_ANNUAL' LIMIT 1") ?: $feeTypeId;
                $db->execute("CALL sp_add_invoice_item(?, ?, 'Dependent Annual Fees', 'رسوم تابعين سنوية', 1, ?, 0, 0)", [
                    $invoiceId, $depFeeTypeId, $depAmount
                ]);
            }
            if ($lateFee > 0) {
                $lateFeeTypeId = $db->fetchColumn("SELECT id FROM fee_types WHERE fee_code = 'LATE_FEE' LIMIT 1") ?: $feeTypeId;
                $db->execute("CALL sp_add_invoice_item(?, ?, 'Late Renewal Fee', 'غرامة تأخير تجديد', 1, ?, 0, 0)", [
                    $invoiceId, $lateFeeTypeId, $lateFee
                ]);
            }

            // Issue invoice
            $db->execute("CALL sp_issue_invoice(?, ?, @issue_result)", [$invoiceId, Auth::id()]);

            // Create subscription record
            $subId = $db->insert('member_subscriptions', [
                'member_id'              => $data['member_id'],
                'subscription_period_id' => $data['subscription_period_id'],
                'membership_type_id'     => $member['membership_type_id'],
                'invoice_id'             => $invoiceId,
                'amount'                 => $amount,
                'discount_amount'        => $discount,
                'net_amount'             => $net + $depAmount + $lateFee,
                'paid_amount'            => 0,
                'balance_due'            => $net + $depAmount + $lateFee,
                'dependents_count'       => $depCount,
                'dependents_amount'      => $depAmount,
                'start_date'             => $period['start_date'],
                'end_date'               => $period['end_date'],
                'status'                 => 'pending',
                'renewed_from_id'        => $previousSub ? $previousSub['id'] : null,
                'is_renewal'             => $previousSub ? 1 : 0,
                'renewal_date'           => $previousSub ? date('Y-m-d') : null,
                'late_fee'               => $lateFee,
                'notes'                  => $data['notes'] ?? null,
                'created_by'             => Auth::id(),
            ]);

            // Log renewal
            if ($previousSub) {
                $db->insert('subscription_renewal_log', [
                    'member_id'           => $data['member_id'],
                    'old_subscription_id' => $previousSub['id'],
                    'new_subscription_id' => $subId,
                    'renewal_date'        => date('Y-m-d'),
                    'renewal_type'        => $lateFee > 0 ? 'late' : 'normal',
                    'previous_type_id'    => $member['membership_type_id'],
                    'new_type_id'         => $member['membership_type_id'],
                    'is_type_change'      => 0,
                    'late_days'           => 0,
                    'late_fee'            => $lateFee,
                    'notes'               => $data['notes'] ?? null,
                    'created_by'          => Auth::id(),
                ]);
            }

            $this->audit('create', 'member_subscriptions', $subId, 'Created subscription for member #' . $data['member_id']);
            $db->commit();

            $this->json([
                'success'  => true,
                'message'  => 'Subscription created successfully',
                'redirect' => '/subscriptions/' . $subId,
            ]);
        } catch (\Exception $e) {
            $db->rollBack();
            Logger::error('Subscription creation failed: ' . $e->getMessage());
            $this->json(['success' => false, 'message' => 'Failed to create subscription'], 500);
        }
    }

    // ══════════════════════════════════════════════════
    //  ELIGIBLE MEMBERS FOR BULK RENEW
    // ══════════════════════════════════════════════════
    public function eligible(Request $request): void
    {
        $db = $this->db();
        $periodId = (int) $request->get('period_id');
        $typeId   = (int) $request->get('type_id', 0);

        $where  = "m.status = 'active' AND m.is_deleted = 0";
        $params = [];

        if ($typeId) {
            $where .= " AND m.membership_type_id = ?";
            $params[] = $typeId;
        }

        if ($periodId) {
            $where .= " AND m.id NOT IN (SELECT member_id FROM member_subscriptions WHERE subscription_period_id = ? AND status NOT IN ('cancelled'))";
            $params[] = $periodId;
        }

        $members = $db->fetchAll(
            "SELECT m.id, m.membership_number, m.full_name_en, m.primary_phone, mt.name_en AS type_name,
                    (SELECT ms.end_date FROM member_subscriptions ms WHERE ms.member_id = m.id AND ms.status IN ('active','expired') ORDER BY ms.end_date DESC LIMIT 1) AS last_sub_end
             FROM members m
             JOIN membership_types mt ON m.membership_type_id = mt.id
             WHERE {$where}
             ORDER BY m.membership_number
             LIMIT 500",
            $params
        );

        $this->json(['success' => true, 'data' => $members]);
    }

    // ══════════════════════════════════════════════════
    //  PROCESS BULK RENEWAL
    // ══════════════════════════════════════════════════
    public function processBulkRenew(Request $request): void
    {
        if (!CSRF::validate($request->csrfToken())) {
            $this->json(['success' => false, 'message' => 'Invalid security token'], 403);
            return;
        }

        $periodId  = (int) $request->post('period_id');
        $memberIds = $request->post('member_ids', []);

        if (!$periodId || empty($memberIds) || !is_array($memberIds)) {
            $this->json(['success' => false, 'message' => 'Select a period and at least one member'], 422);
            return;
        }

        $db = $this->db();
        $period = $db->fetchOne("SELECT * FROM subscription_periods WHERE id = ? AND is_active = 1", [$periodId]);
        if (!$period) {
            $this->json(['success' => false, 'message' => 'Invalid period'], 422);
            return;
        }

        $success = 0;
        $failed  = 0;
        $errors  = [];

        foreach ($memberIds as $mid) {
            $mid = (int) $mid;
            $member = $db->fetchOne("SELECT id, membership_type_id, status FROM members WHERE id = ? AND is_deleted = 0 AND status = 'active'", [$mid]);
            if (!$member) {
                $failed++;
                $errors[] = "Member #{$mid} not found or inactive";
                continue;
            }

            $existing = $db->fetchOne("SELECT id FROM member_subscriptions WHERE member_id = ? AND subscription_period_id = ? AND status NOT IN ('cancelled')", [$mid, $periodId]);
            if ($existing) {
                $failed++;
                $errors[] = "Member #{$mid} already has subscription for this period";
                continue;
            }

            $fee = $db->fetchOne(
                "SELECT amount FROM membership_type_fees WHERE membership_type_id = ? AND fee_type_id = (SELECT id FROM fee_types WHERE fee_code = 'ANNUAL_SUB' LIMIT 1) AND is_active = 1 AND effective_from <= CURDATE() AND (effective_to IS NULL OR effective_to >= CURDATE()) ORDER BY effective_from DESC LIMIT 1",
                [$member['membership_type_id']]
            );
            $amount = $fee ? (float) $fee['amount'] : 0;

            try {
                $db->beginTransaction();

                $db->execute("CALL sp_create_invoice(?, 'subscription', ?, ?, @inv_id, @inv_num)", [$mid, $period['end_date'], Auth::id()]);
                $invResult = $db->fetchOne("SELECT @inv_id AS id, @inv_num AS num");
                $feeTypeId = $db->fetchColumn("SELECT id FROM fee_types WHERE fee_code = 'ANNUAL_SUB' LIMIT 1");
                if ($feeTypeId && $amount > 0) {
                    $db->execute("CALL sp_add_invoice_item(?, ?, 'Annual Subscription', 'اشتراك سنوي', 1, ?, 0, 0)", [$invResult['id'], $feeTypeId, $amount]);
                }
                $db->execute("CALL sp_issue_invoice(?, ?, @r)", [$invResult['id'], Auth::id()]);

                $previousSub = $db->fetchOne("SELECT id FROM member_subscriptions WHERE member_id = ? AND status IN ('active','expired') ORDER BY end_date DESC LIMIT 1", [$mid]);

                $db->insert('member_subscriptions', [
                    'member_id' => $mid, 'subscription_period_id' => $periodId,
                    'membership_type_id' => $member['membership_type_id'], 'invoice_id' => $invResult['id'],
                    'amount' => $amount, 'discount_amount' => 0, 'net_amount' => $amount,
                    'paid_amount' => 0, 'balance_due' => $amount, 'dependents_count' => 0, 'dependents_amount' => 0,
                    'start_date' => $period['start_date'], 'end_date' => $period['end_date'],
                    'status' => 'pending', 'renewed_from_id' => $previousSub['id'] ?? null,
                    'is_renewal' => $previousSub ? 1 : 0, 'renewal_date' => $previousSub ? date('Y-m-d') : null,
                    'late_fee' => 0, 'created_by' => Auth::id(),
                ]);

                $db->commit();
                $success++;
            } catch (\Exception $e) {
                $db->rollBack();
                $failed++;
                $errors[] = "Member #{$mid}: " . $e->getMessage();
            }
        }

        $this->audit('create', 'member_subscriptions', null, "Bulk renewal: {$success} success, {$failed} failed");

        $this->json([
            'success' => true,
            'message' => "Processed: {$success} renewed, {$failed} failed",
            'success_count' => $success,
            'failed_count'  => $failed,
            'errors'        => $errors,
        ]);
    }

    // ══════════════════════════════════════════════════
    //  PERIODS DATATABLE
    // ══════════════════════════════════════════════════
    public function periodsDatatable(Request $request): void
    {
        $db   = $this->db();
        $draw = (int) $request->get('draw', 1);

        $rows = $db->fetchAll(
            "SELECT sp.*,
                    (SELECT COUNT(*) FROM member_subscriptions ms WHERE ms.subscription_period_id = sp.id AND ms.status NOT IN ('cancelled')) AS sub_count
             FROM subscription_periods sp
             ORDER BY sp.start_date DESC"
        );

        $data = [];
        foreach ($rows as $r) {
            $data[] = [
                'id'         => $r['id'],
                'period_code'=> e($r['period_code']),
                'name_en'    => e($r['name_en']),
                'name_ar'    => e($r['name_ar']),
                'start_date' => format_date($r['start_date']),
                'end_date'   => format_date($r['end_date']),
                'grace_end'  => $r['grace_end_date'] ? format_date($r['grace_end_date']) : '-',
                'sub_count'  => number_format($r['sub_count']),
                'is_active'  => $r['is_active'] ? '<span class="badge bg-success">Active</span>' : '<span class="badge bg-secondary">Inactive</span>',
                'actions'    => '<button class="btn btn-sm btn-outline-warning btn-edit-period" data-id="' . $r['id'] . '"><i class="fas fa-edit"></i></button>',
            ];
        }

        $this->json(['draw' => $draw, 'recordsTotal' => count($data), 'recordsFiltered' => count($data), 'data' => $data]);
    }

    public function getPeriod(Request $request): void
    {
        $id = (int) $request->routeParam('id');
        $row = $this->db()->fetchOne("SELECT * FROM subscription_periods WHERE id = ?", [$id]);
        if (!$row) { $this->json(['success' => false, 'message' => 'Not found'], 404); return; }
        $this->json(['success' => true, 'data' => $row]);
    }

    public function storePeriod(Request $request): void
    {
        if (!CSRF::validate($request->csrfToken())) { $this->json(['success' => false, 'message' => 'CSRF'], 403); return; }

        $v = new Validator($request->all(), [
            'period_code' => 'required|string|max:20',
            'name_en'     => 'required|string|max:200',
            'name_ar'     => 'required|string|max:200',
            'start_date'  => 'required|date',
            'end_date'    => 'required|date',
            'grace_end_date' => 'nullable|date',
            'is_active'   => 'nullable|boolean',
        ]);
        if ($v->fails()) { $this->json(['success' => false, 'errors' => $v->errors()], 422); return; }

        $d = $v->validated();
        $d['is_active'] = $d['is_active'] ?? 1;

        $id = $this->db()->insert('subscription_periods', $d);
        $this->audit('create', 'subscription_periods', $id, 'Created subscription period: ' . $d['period_code']);
        $this->json(['success' => true, 'message' => 'Period created', 'id' => $id]);
    }

    public function updatePeriod(Request $request): void
    {
        if (!CSRF::validate($request->csrfToken())) { $this->json(['success' => false, 'message' => 'CSRF'], 403); return; }

        $id = (int) $request->routeParam('id');
        $v = new Validator($request->all(), [
            'period_code' => 'required|string|max:20',
            'name_en'     => 'required|string|max:200',
            'name_ar'     => 'required|string|max:200',
            'start_date'  => 'required|date',
            'end_date'    => 'required|date',
            'grace_end_date' => 'nullable|date',
            'is_active'   => 'nullable|boolean',
        ]);
        if ($v->fails()) { $this->json(['success' => false, 'errors' => $v->errors()], 422); return; }

        $d = $v->validated();
        $d['is_active'] = $d['is_active'] ?? 0;

        $this->db()->update('subscription_periods', $d, 'id = ?', [$id]);
        $this->audit('update', 'subscription_periods', $id, 'Updated subscription period');
        $this->json(['success' => true, 'message' => 'Period updated']);
    }
}