<?php

namespace App\Controllers;

use App\Core\Auth;
use App\Core\Database;
use App\Core\Permission;

require_once __DIR__ . '/../Onboarding/Support.php';

class OnboardingAppController
{
    /** Staff console — Rachel/Sara, must be logged in and assigned the project. */
    public function index(): void
    {
        $user = Permission::requireLogin();
        $db = Database::connection();
        if (empty($user['is_super_admin'])) {
            $stmt = $db->prepare(
                "SELECT 1 FROM user_projects up JOIN projects p ON p.id = up.project_id
                 WHERE up.user_type=:t AND up.user_id=:id AND p.code='employee_onboarding'"
            );
            $stmt->execute(['t' => $user['user_type'], 'id' => $user['user_id']]);
            if (!$stmt->fetch()) { http_response_code(403); echo 'You do not have access to Employee Onboarding.'; return; }
        }
        $applicantToken = '';
        $applicantPhase = 'A';
        $applicantHireJson = 'null';

        // S2: populate the Job Site dropdown from the existing `sites`
        // table — same table the rest of the Workspace already uses.
        $sitesJson = json_encode(array_column($db->query('SELECT name FROM sites ORDER BY name')->fetchAll(), 'name'));

        $notifStmt = $db->prepare(
            "SELECT * FROM notifications WHERE user_type=:t AND user_id=:id AND is_read=0 AND link LIKE '/onboarding%' ORDER BY created_at DESC LIMIT 20"
        );
        $notifStmt->execute(['t' => $user['user_type'], 'id' => $user['user_id']]);
        $notifications = $notifStmt->fetchAll();

        require __DIR__ . '/../Views/onboarding/app.php';
    }

    /** Marks one or more notifications read, then redirects — used by the
     *  header notification chip's link (a plain <a>, not an AJAX call). */
    public function notifOpen(): void
    {
        $user = Permission::requireLogin();
        $ids = array_filter(array_map('intval', explode(',', $_GET['ids'] ?? '')));
        if ($ids) {
            $db = Database::connection();
            $placeholders = implode(',', array_fill(0, count($ids), '?'));
            $params = array_merge($ids, [$user['user_type'], $user['user_id']]);
            $db->prepare("UPDATE notifications SET is_read=1 WHERE id IN ($placeholders) AND user_type=? AND user_id=?")->execute($params);
        }
        $to = $_GET['to'] ?? '/onboarding';
        // Only allow redirecting to our own app's URLs — never an open redirect.
        if (strpos($to, '/onboarding') !== 0) $to = '/onboarding';
        header('Location: ' . $to);
    }

    /** Marks one notification read (called by the banner's "Mark as read" button). */
    public function notifRead(): void
    {
        $user = Permission::requireLogin();
        $body = json_decode(file_get_contents('php://input'), true) ?: [];
        $db = Database::connection();
        $db->prepare('UPDATE notifications SET is_read=1 WHERE id=? AND user_type=? AND user_id=?')
           ->execute([(int)($body['id'] ?? 0), $user['user_type'], $user['user_id']]);
        header('Content-Type: application/json');
        echo json_encode(['ok' => true]);
    }

    /** Participant — no login, secure token in the URL only. */
    public function apply(): void
    {
        $token = $_GET['token'] ?? '';
        $phase = strtoupper($_GET['phase'] ?? 'A') === 'B' ? 'B' : 'A';

        $db = Database::connection();
        $stmt = $db->prepare('SELECT * FROM onboarding_hires WHERE token=?');
        $stmt->execute([$token]);
        $hire = $stmt->fetch();

        $applicantToken = $token;
        $applicantPhase = $phase;
        $applicantHireJson = $hire ? json_encode($this->hireToJs($hire)) : 'null';
        $notifications = []; // participants never see staff notifications

        require __DIR__ . '/../Views/onboarding/app.php';
    }

    private function hireToJs(array $r): array
    {
        return [
            'token' => $r['token'], 'eid' => $r['eid'], 'status' => $r['status'],
            'first' => $r['first'], 'middle' => $r['middle'], 'last' => $r['last'],
            'phone' => $r['phone'], 'email' => $r['email'],
            'address' => $r['address'], 'city' => $r['city'], 'state' => $r['state'], 'zip' => $r['zip'],
            'guardCard' => $r['guard_card'], 'guardCardExp' => $r['guard_card_exp'],
            'dl' => $r['dl'], 'dlExp' => $r['dl_exp'], 'firearmsPermit' => $r['firearms_permit'],
            'position' => $r['position'], 'site' => $r['site'],
            'hire' => $r['hire_date'], 'hireType' => $r['hire_type'], 'empStatus' => $r['emp_status'],
            'payRate' => $r['pay_rate'], 'payFreq' => $r['pay_freq'], 'hrRep' => $r['hr_rep'],
            'schedule' => json_decode($r['schedule_json'] ?? '{}', true) ?: [],
        ];
    }

    /** Compact, read-only status dashboard — embedded via iframe directly
     *  on the Workspace project page, so HR can see progress without
     *  opening the full onboarding console. */
    public function embed(): void
    {
        $user = Permission::requireLogin();
        $db = Database::connection();
        if (empty($user['is_super_admin'])) {
            $stmt = $db->prepare(
                "SELECT 1 FROM user_projects up JOIN projects p ON p.id = up.project_id
                 WHERE up.user_type=:t AND up.user_id=:id AND p.code='employee_onboarding'"
            );
            $stmt->execute(['t' => $user['user_type'], 'id' => $user['user_id']]);
            if (!$stmt->fetch()) { http_response_code(403); echo 'You do not have access to Employee Onboarding.'; return; }
        }

        // Ownership visibility — mirrors actionList() in
        // OnboardingApiController. Super admin sees everything (including
        // historical rows with no owner); everyone else sees records that
        // match their own authenticated session identity, OR records with
        // no owner recorded at all (created_by_type/created_by_id both
        // NULL) — keeping every pre-existing historical hire visible to
        // every currently-authorized user exactly as it is today.
        // ($user is already server-side here via Permission::requireLogin(),
        // never frontend-supplied).
        if (!empty($user['is_super_admin'])) {
            $rows = $db->query('SELECT * FROM onboarding_hires ORDER BY updated_at DESC')->fetchAll();
        } else {
            $stmt = $db->prepare(
                'SELECT * FROM onboarding_hires WHERE (created_by_type = ? AND created_by_id = ?) OR (created_by_type IS NULL AND created_by_id IS NULL) ORDER BY updated_at DESC'
            );
            $stmt->execute([$user['user_type'], (int)$user['user_id']]);
            $rows = $stmt->fetchAll();
        }
        $api = new OnboardingApiController();
        $hires = [];
        foreach ($rows as $r) {
            $h = $this->hireRowToArray($r);
            $h = $api->attachExtrasPublic($h, (int)$r['id']);
            $hires[] = $h;
        }

        require __DIR__ . '/../Views/onboarding/embed.php';
    }

    private function hireRowToArray(array $r): array
    {
        return [
            'first' => $r['first'], 'last' => $r['last'], 'email' => $r['email'],
            'position' => $r['position'], 'site' => $r['site'], 'status' => $r['status'],
        ];
    }

    /** Secure download for generated PDFs (staff only). */
    public function download(): void
    {
        Permission::requireLogin();
        $cfg = require __DIR__ . '/../../config/config.php';
        $rel = $_GET['path'] ?? '';
        // Prevent path traversal outside the storage root.
        $base = realpath(rtrim($cfg['storage_path'] ?? '', '/'));
        $full = realpath($base . '/' . $rel);
        if (!$full || strpos($full, $base) !== 0 || !is_file($full)) {
            http_response_code(404); echo 'File not found.'; return;
        }
        // Serve inline (not as a forced attachment). Links open this in a new
        // tab (target="_blank"); with "attachment" the browser starts a file
        // download in that blank tab and then tries to navigate the tab to
        // the local downloaded copy before the OS has finished writing it,
        // producing an intermittent "This site can't be reached" on the
        // first click (a retry works because the file exists by then).
        // Serving inline lets the browser render the PDF directly, which
        // fixes the race without changing how forms are viewed/saved.
        header('Content-Type: application/pdf');
        header('Content-Disposition: inline; filename="' . basename($full) . '"');
        readfile($full);
    }
}
