<?php
require_once __DIR__ . '/BaseController.php';

class GuestPassController extends BaseController
{
    public function index(Request $request): void
    {
        $db = Database::getInstance();
        $stats = [
            'active_today' => (int) $db->fetchColumn("SELECT COUNT(*) FROM guest_passes WHERE valid_date = CURDATE() AND status IN ('issued','active')"),
            'issued_month' => (int) $db->fetchColumn("SELECT COUNT(*) FROM guest_passes WHERE MONTH(valid_date) = MONTH(CURDATE()) AND YEAR(valid_date) = YEAR(CURDATE())"),
            'checked_in' => (int) $db->fetchColumn("SELECT COUNT(*) FROM guest_passes WHERE valid_date = CURDATE() AND status = 'active' AND check_in_time IS NOT NULL AND check_out_time IS NULL"),
        ];
        $passTypes = $db->fetchAll("SELECT id, name_en, name_ar FROM guest_pass_types WHERE is_active = 1 ORDER BY name_en");

        $this->view('guests/index', [
            'title' => lang('cards.guest_passes'),
            'breadcrumbs' => [['label' => lang('cards.guests')], ['label' => lang('cards.guest_passes')]],
            'stats' => $stats,
            'passTypes' => $passTypes,
        ]);
    }

    public function datatable(Request $request): void
    {
        $status = $request->get('filter_status', '');
        $dateFrom = $request->get('filter_date_from', '');
        $dateTo = $request->get('filter_date_to', '');

        $where = "WHERE 1=1";
        $params = [];
        if ($status) { $where .= " AND gp.status = ?"; $params[] = $status; }
        if ($dateFrom) { $where .= " AND gp.valid_date >= ?"; $params[] = $dateFrom; }
        if ($dateTo) { $where .= " AND gp.valid_date <= ?"; $params[] = $dateTo; }

        $baseQuery = "SELECT gp.id, gp.pass_number, gp.guest_name, gp.guest_phone, gp.valid_date,
                       gp.fee_amount, gp.status, gp.check_in_time, gp.check_out_time,
                       gpt.name_en AS type_name,
                       m.membership_number, m.full_name_en AS host_name
                       FROM guest_passes gp
                       LEFT JOIN guest_pass_types gpt ON gp.pass_type_id = gpt.id
                       LEFT JOIN members m ON gp.host_member_id = m.id
                       {$where}";

        $columns = [
            ['db' => 'id', 'searchable' => false],
            ['db' => 'pass_number', 'searchable' => true],
            ['db' => 'guest_name', 'searchable' => true],
            ['db' => 'host_name', 'searchable' => true],
            ['db' => 'type_name', 'searchable' => true],
            ['db' => 'valid_date', 'searchable' => false],
            ['db' => 'status', 'searchable' => true],
            ['db' => 'guest_phone', 'searchable' => true],
        ];

        $this->handleDataTable($request, $baseQuery, $params, $columns, 'gp.id DESC');
    }

    public function create(Request $request): void
    {
        $db = Database::getInstance();
        $passTypes = $db->fetchAll("SELECT * FROM guest_pass_types WHERE is_active = 1 ORDER BY name_en");

        $this->view('guests/create', [
            'title' => lang('cards.issue_guest_pass'),
            'breadcrumbs' => [['label' => lang('cards.guests')], ['label' => lang('cards.guest_passes'), 'url' => '/guests'], ['label' => lang('common.create')]],
            'passTypes' => $passTypes,
        ]);
    }

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

        $validator = new Validator($request->all(), [
            'host_member_id' => 'required|integer|exists:members,id',
            'pass_type_id' => 'required|integer|exists:guest_pass_types,id',
            'guest_name' => 'required|string|max:300',
            'valid_date' => 'required|date',
        ]);
        if ($validator->fails()) { $this->json(['success' => false, 'errors' => $validator->errors()], 422); return; }

        $db = Database::getInstance();
        $data = $validator->validated();

        // Check blacklist
        $nationalId = $request->post('guest_national_id', '');
        if ($nationalId) {
            $blacklisted = $db->fetchOne("SELECT id FROM guest_blacklist WHERE guest_national_id = ? AND status = 'active' AND (expires_at IS NULL OR expires_at > CURDATE())", [$nationalId]);
            if ($blacklisted) {
                $this->json(['success' => false, 'message' => lang('cards.guest_blacklisted')], 422);
                return;
            }
        }

        // Check guest policy
        $member = $db->fetchOne("SELECT membership_type_id FROM members WHERE id = ?", [$data['host_member_id']]);
        $policyViolation = $this->checkGuestPolicy($db, $data['host_member_id'], $member['membership_type_id'] ?? null, $data['pass_type_id']);
        if ($policyViolation) {
            $this->json(['success' => false, 'message' => $policyViolation], 422);
            return;
        }

        $passType = $db->fetchOne("SELECT * FROM guest_pass_types WHERE id = ?", [$data['pass_type_id']]);
        $passNumber = SequenceGenerator::next('guest_pass_number');

        $id = $db->insert('guest_passes', [
            'pass_number'     => $passNumber,
            'pass_type_id'    => $data['pass_type_id'],
            'host_member_id'  => $data['host_member_id'],
            'guest_name'      => $data['guest_name'],
            'guest_phone'     => $request->post('guest_phone', ''),
            'guest_national_id' => $nationalId ?: null,
            'guest_email'     => $request->post('guest_email', '') ?: null,
            'guest_gender'    => $request->post('guest_gender', '') ?: null,
            'valid_date'      => $data['valid_date'],
            'valid_from_time' => $request->post('valid_from_time') ?: null,
            'valid_to_time'   => $request->post('valid_to_time') ?: null,
            'fee_amount'      => $passType['fee'] ?? 0,
            'fee_paid'        => 0,
            'status'          => 'issued',
            'created_by'      => Auth::id(),
            'created_at'      => date('Y-m-d H:i:s'),
        ]);

        AuditLog::log('create', 'cards', 'guest_passes', $id, "Guest pass {$passNumber} issued for {$data['guest_name']}");
        $this->json(['success' => true, 'message' => lang('cards.guest_pass_issued'), 'redirect' => '/guests/' . $id]);
    }

    public function show(Request $request): void
    {
        $id = (int) $request->routeParam('id');
        $db = Database::getInstance();
        $pass = $db->fetchOne(
            "SELECT gp.*, gpt.name_en AS type_name, gpt.name_ar AS type_name_ar,
                    m.membership_number, m.full_name_en AS host_name, m.full_name_ar AS host_name_ar, m.primary_phone AS host_phone
             FROM guest_passes gp
             LEFT JOIN guest_pass_types gpt ON gp.pass_type_id = gpt.id
             LEFT JOIN members m ON gp.host_member_id = m.id
             WHERE gp.id = ?", [$id]
        );
        if (!$pass) { $this->abort(404, 'Not found'); return; }

        $visits = $db->fetchAll("SELECT * FROM guest_visits WHERE guest_pass_id = ? ORDER BY visit_date DESC", [$id]);

        $this->view('guests/show', [
            'title' => lang('cards.guest_pass') . ' - ' . $pass['pass_number'],
            'breadcrumbs' => [['label' => lang('cards.guests')], ['label' => lang('cards.guest_passes'), 'url' => '/guests'], ['label' => $pass['pass_number']]],
            'pass' => $pass,
            'visits' => $visits,
        ]);
    }

    public function checkIn(Request $request): void
    {
        if (!CSRF::validate($request->csrfToken())) { $this->json(['success' => false, 'message' => 'Invalid token'], 403); return; }
        $id = (int) $request->routeParam('id');
        $db = Database::getInstance();
        $pass = $db->fetchOne("SELECT * FROM guest_passes WHERE id = ? AND status IN ('issued','active')", [$id]);
        if (!$pass) { $this->json(['success' => false, 'message' => 'Pass not found or not valid'], 404); return; }
        if ($pass['valid_date'] !== date('Y-m-d')) { $this->json(['success' => false, 'message' => 'Pass not valid for today'], 422); return; }

        $db->update('guest_passes', [
            'status' => 'active',
            'check_in_time' => date('Y-m-d H:i:s'),
            'checked_in_by' => Auth::id(),
        ], 'id = ?', [$id]);

        $this->json(['success' => true, 'message' => lang('cards.guest_checked_in')]);
    }

    public function checkOut(Request $request): void
    {
        if (!CSRF::validate($request->csrfToken())) { $this->json(['success' => false, 'message' => 'Invalid token'], 403); return; }
        $id = (int) $request->routeParam('id');
        $db = Database::getInstance();

        $db->update('guest_passes', [
            'status' => 'used',
            'check_out_time' => date('Y-m-d H:i:s'),
            'checked_out_by' => Auth::id(),
        ], 'id = ? AND status = ?', [$id, 'active']);

        $this->json(['success' => true, 'message' => lang('cards.guest_checked_out')]);
    }

    public function cancel(Request $request): void
    {
        if (!CSRF::validate($request->csrfToken())) { $this->json(['success' => false, 'message' => 'Invalid token'], 403); return; }
        $id = (int) $request->routeParam('id');
        $db = Database::getInstance();
        $db->update('guest_passes', ['status' => 'cancelled'], 'id = ? AND status IN (?,?)', [$id, 'issued', 'active']);
        AuditLog::log('update', 'cards', 'guest_passes', $id, "Guest pass cancelled");
        $this->json(['success' => true, 'message' => lang('cards.guest_pass_cancelled')]);
    }

    private function checkGuestPolicy(Database $db, int $memberId, ?int $membershipTypeId, int $passTypeId): ?string
    {
        $rules = $db->fetchAll(
            "SELECT * FROM guest_policy_rules WHERE is_active = 1 AND (membership_type_id IS NULL OR membership_type_id = ?) AND (guest_pass_type_id IS NULL OR guest_pass_type_id = ?)",
            [$membershipTypeId, $passTypeId]
        );
        foreach ($rules as $rule) {
            if ($rule['max_visits_per_month']) {
                $monthCount = (int) $db->fetchColumn("SELECT COUNT(*) FROM guest_passes WHERE host_member_id = ? AND MONTH(valid_date) = MONTH(CURDATE()) AND YEAR(valid_date) = YEAR(CURDATE()) AND status != 'cancelled'", [$memberId]);
                if ($monthCount >= $rule['max_visits_per_month']) return lang('cards.guest_month_limit');
            }
            if ($rule['max_visits_per_year']) {
                $yearCount = (int) $db->fetchColumn("SELECT COUNT(*) FROM guest_passes WHERE host_member_id = ? AND YEAR(valid_date) = YEAR(CURDATE()) AND status != 'cancelled'", [$memberId]);
                if ($yearCount >= $rule['max_visits_per_year']) return lang('cards.guest_year_limit');
            }
        }
        return null;
    }
}