<?php
class GuestController extends Controller
{
    public function index(Request $request): void
    {
        $db = $this->db();
        $stats = [
            'today_active'  => (int)$db->fetchColumn("SELECT COUNT(*) FROM guest_passes WHERE valid_date = CURDATE() AND status IN ('issued','active')"),
            'today_used'    => (int)$db->fetchColumn("SELECT COUNT(*) FROM guest_passes WHERE valid_date = CURDATE() AND status = 'used'"),
            'month_total'   => (int)$db->fetchColumn("SELECT COUNT(*) FROM guest_passes WHERE MONTH(valid_date) = MONTH(CURDATE()) AND YEAR(valid_date) = YEAR(CURDATE())"),
        ];

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

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

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

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

        $validator = new Validator($request->all(), [
            'pass_type_id'     => 'required|integer|exists:guest_pass_types,id',
            'host_member_id'   => 'required|integer|exists:members,id',
            'guest_name'       => 'required|string|max:300',
            'guest_phone'      => 'nullable|string|max:20',
            'guest_national_id'=> 'nullable|string|max:20',
            'guest_gender'     => 'nullable|in:male,female',
            'valid_date'       => 'required|date',
        ]);

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

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

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

        // Check guest policy
        $member = $db->fetchOne("SELECT id, membership_type_id, status FROM members WHERE id = ? AND is_deleted = 0", [$data['host_member_id']]);
        if (!$member || $member['status'] !== 'active') {
            $this->json(['success' => false, 'message' => lang('cards.host_not_active')], 422);
            return;
        }

        $policy = $db->fetchOne(
            "SELECT * FROM guest_policy_rules WHERE (membership_type_id = ? OR membership_type_id IS NULL) AND (guest_pass_type_id = ? OR guest_pass_type_id IS NULL) AND is_active = 1 ORDER BY membership_type_id DESC, guest_pass_type_id DESC LIMIT 1",
            [$member['membership_type_id'], $data['pass_type_id']]
        );

        if ($policy) {
            if ($policy['max_visits_per_month']) {
                $monthCount = (int)$db->fetchColumn(
                    "SELECT COUNT(*) FROM guest_passes WHERE host_member_id = ? AND MONTH(valid_date) = MONTH(?) AND YEAR(valid_date) = YEAR(?)",
                    [$data['host_member_id'], $data['valid_date'], $data['valid_date']]
                );
                if ($monthCount >= $policy['max_visits_per_month']) {
                    $this->json(['success' => false, 'message' => lang('cards.guest_monthly_limit')], 422);
                    return;
                }
            }

            if ($policy['same_guest_max_visits_per_month'] && !empty($data['guest_national_id'])) {
                $sameGuestMonth = (int)$db->fetchColumn(
                    "SELECT COUNT(*) FROM guest_passes WHERE host_member_id = ? AND guest_national_id = ? AND MONTH(valid_date) = MONTH(?) AND YEAR(valid_date) = YEAR(?)",
                    [$data['host_member_id'], $data['guest_national_id'], $data['valid_date'], $data['valid_date']]
                );
                if ($sameGuestMonth >= $policy['same_guest_max_visits_per_month']) {
                    $this->json(['success' => false, 'message' => lang('cards.same_guest_limit')], 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'       => $data['guest_phone'] ?? null,
            'guest_national_id' => $data['guest_national_id'] ?? null,
            'guest_gender'      => $data['guest_gender'] ?? null,
            'valid_date'        => $data['valid_date'],
            'fee_amount'        => $passType['fee'],
            'fee_paid'          => 0,
            'status'            => 'issued',
            'created_by'        => Auth::id(),
        ]);

        $this->audit('create', 'guest_passes', $id, "Guest pass issued: {$passNumber} for {$data['guest_name']}");

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

    public function show(Request $request): void
    {
        $id = (int)$request->routeParam('id');
        $db = $this->db();

        $pass = $db->fetchOne(
            "SELECT gp.*, gpt.name_en AS type_name_en, gpt.name_ar AS type_name_ar,
                    m.membership_number, m.full_name_en AS host_name_en, m.full_name_ar AS host_name_ar, m.primary_phone AS host_phone
             FROM guest_passes gp
             JOIN guest_pass_types gpt ON gp.pass_type_id = gpt.id
             JOIN members m ON gp.host_member_id = m.id
             WHERE gp.id = ?", [$id]
        );

        if (!$pass) {
            $this->abort(404, 'Guest pass not found');
        }

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

        $this->view('guests/show', [
            'title'       => lang('cards.pass_details'),
            'breadcrumbs' => [
                ['label' => lang('cards.guests'), '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 CSRF token'], 403);
            return;
        }

        $id = (int)$request->routeParam('id');
        $db = $this->db();

        $pass = $db->fetchOne("SELECT * FROM guest_passes WHERE id = ? AND status IN ('issued','active') AND valid_date = CURDATE()", [$id]);
        if (!$pass) {
            $this->json(['success' => false, 'message' => lang('cards.pass_not_valid')], 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]);

        $db->insert('guest_visits', [
            'guest_pass_id' => $id,
            'visit_date'    => date('Y-m-d'),
            'check_in'      => date('Y-m-d H:i:s'),
            'host_present'  => 1,
            'recorded_by'   => Auth::id(),
        ]);

        $this->audit('update', 'guest_passes', $id, "Guest checked in: {$pass['pass_number']}");
        $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 CSRF token'], 403);
            return;
        }

        $id = (int)$request->routeParam('id');
        $db = $this->db();

        $pass = $db->fetchOne("SELECT * FROM guest_passes WHERE id = ? AND status = 'active'", [$id]);
        if (!$pass) {
            $this->json(['success' => false, 'message' => lang('cards.pass_not_active')], 422);
            return;
        }

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

        $visit = $db->fetchOne("SELECT id FROM guest_visits WHERE guest_pass_id = ? ORDER BY id DESC LIMIT 1", [$id]);
        if ($visit) {
            $db->update('guest_visits', ['check_out' => date('Y-m-d H:i:s')], 'id = ?', [$visit['id']]);
        }

        $this->audit('update', 'guest_passes', $id, "Guest checked out: {$pass['pass_number']}");
        $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 CSRF token'], 403);
            return;
        }

        $id = (int)$request->routeParam('id');
        $db = $this->db();

        $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 cannot be cancelled'], 404);
            return;
        }

        $db->update('guest_passes', ['status' => 'cancelled'], 'id = ?', [$id]);
        $this->audit('update', 'guest_passes', $id, "Guest pass cancelled: {$pass['pass_number']}");

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

    public function blacklist(Request $request): void
    {
        $this->view('guests/blacklist', [
            'title'       => lang('cards.guest_blacklist'),
            'breadcrumbs' => [
                ['label' => lang('cards.guests'), 'url' => '/guests'],
                ['label' => lang('cards.guest_blacklist')],
            ],
        ]);
    }

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

        $validator = new Validator($request->all(), [
            'guest_name'        => 'required|string|max:300',
            'guest_national_id' => 'nullable|string|max:20',
            'guest_phone'       => 'nullable|string|max:20',
            'reason'            => 'required|string|max:1000',
            'expires_at'        => 'nullable|date',
        ]);

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

        $data = $validator->validated();
        $id = $this->db()->insert('guest_blacklist', [
            'guest_name'        => $data['guest_name'],
            'guest_national_id' => $data['guest_national_id'] ?? null,
            'guest_phone'       => $data['guest_phone'] ?? null,
            'reason'            => $data['reason'],
            'blacklisted_date'  => date('Y-m-d'),
            'blacklisted_by'    => Auth::id(),
            'expires_at'        => $data['expires_at'] ?? null,
            'status'            => 'active',
        ]);

        $this->audit('create', 'guest_blacklist', $id, "Guest blacklisted: {$data['guest_name']}");
        $this->json(['success' => true, 'message' => lang('cards.blacklist_added')]);
    }

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

        $id = (int)$request->routeParam('id');
        $reason = trim($request->post('removal_reason', ''));
        $db = $this->db();

        $db->update('guest_blacklist', [
            'status'          => 'removed',
            'removed_by'      => Auth::id(),
            'removed_at'      => date('Y-m-d H:i:s'),
            'removal_reason'  => $reason,
        ], 'id = ?', [$id]);

        $this->audit('update', 'guest_blacklist', $id, "Removed from blacklist");
        $this->json(['success' => true, 'message' => lang('cards.blacklist_removed')]);
    }
}