<?php
namespace App\Controllers;

require_once BASE_PATH . '/app/helpers/permissions.php';

use App\Core\Database;

class AdminBusinessToolsController
{
    protected function db()
    {
        return Database::getInstance();
    }

    private function startSession(): void
    {
        if (session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
        }
    }

    private function role(): string
    {
        return (string)($_SESSION['conference_role'] ?? $_SESSION['role'] ?? $_SESSION['user_role'] ?? '');
    }

    private function requireAccess(): void
    {
        $this->startSession();

        if (empty($_SESSION['user_id'])) {
            header("Location: /easychair/login");
            exit;
        }

        if (empty($_SESSION['conference_id'])) {
            header("Location: /easychair/select-conference");
            exit;
        }

        if (!in_array($this->role(), ['super_admin','org_admin','admin','organizer','conference_chair','track_chair','section_editor'], true)) {
            http_response_code(403);
            exit(function_exists('t') ? t('msg.access_denied', 'Access denied.') : 'Access denied.');
        }
    }

    private function conference(): array
    {
        $stmt = $this->db()->prepare("SELECT * FROM conferences WHERE id=? LIMIT 1");
        $stmt->execute([(int)$_SESSION['conference_id']]);
        $c = $stmt->fetch(\PDO::FETCH_ASSOC);

        if (!$c) {
            exit('Conference not found.');
        }

        if ($this->role() !== 'super_admin' && (int)$c['org_id'] !== (int)($_SESSION['org_id'] ?? 0)) {
            http_response_code(403);
            exit(function_exists('t') ? t('msg.access_denied', 'Access denied.') : 'Access denied.');
        }

        return $c;
    }

    private function cols(string $table): array
    {
        try {
            $stmt = $this->db()->query("DESCRIBE {$table}");
            return array_map(fn($r) => $r['Field'], $stmt->fetchAll(\PDO::FETCH_ASSOC));
        } catch (\Throwable $e) {
            return [];
        }
    }

    private function insertDynamic(string $table, array $data): void
    {
        $cols = $this->cols($table);
        $data = array_filter($data, fn($k) => in_array($k, $cols, true), ARRAY_FILTER_USE_KEY);

        if (!$data) {
            return;
        }

        $names = array_keys($data);
        $sql = "INSERT INTO {$table} (`" . implode('`,`', $names) . "`) VALUES (" . implode(',', array_fill(0, count($names), '?')) . ")";
        $stmt = $this->db()->prepare($sql);
        $stmt->execute(array_values($data));
    }

    private function deleteById(string $table, int $id, array $conference): void
    {
        $stmt = $this->db()->prepare("DELETE FROM {$table} WHERE id=? AND conference_id=? AND org_id=?");
        $stmt->execute([$id, (int)$conference['id'], (int)$conference['org_id']]);
    }

    private function view(string $tool, array $data = []): void
    {
        extract($data);

        ob_start();
        require BASE_PATH . '/app/views/admin/business_tools/index.php';
        $content = ob_get_clean();

        require BASE_PATH . '/app/views/layouts/admin_layout.php';
    }

    public function committeeImages()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/committee-images', 'view'); }
        $conference = $this->conference();

        $stmt = $this->db()->prepare("
            SELECT *
            FROM conference_committee_people
            WHERE conference_id=? AND org_id=?
            ORDER BY sort_order, id DESC
        ");
        $stmt->execute([(int)$conference['id'], (int)$conference['org_id']]);
        $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $this->view('committee_images', compact('conference','rows'));
    }

    public function saveCommitteeImage()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/committee-images', 'create'); }
        $conference = $this->conference();

        $imagePath = null;

        if (!empty($_FILES['image']['name']) && is_uploaded_file($_FILES['image']['tmp_name'])) {
            $dir = BASE_PATH . '/public/uploads/committee/' . (int)$conference['id'];
            if (!is_dir($dir)) {
                mkdir($dir, 0775, true);
            }

            $ext = strtolower(pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION));
            if (!in_array($ext, ['jpg','jpeg','png','webp','gif'], true)) {
                $ext = 'jpg';
            }

            $name = 'committee_' . time() . '_' . mt_rand(1000,9999) . '.' . $ext;
            move_uploaded_file($_FILES['image']['tmp_name'], $dir . '/' . $name);
            $imagePath = 'uploads/committee/' . (int)$conference['id'] . '/' . $name;
        }

        $this->insertDynamic('conference_committee_people', [
            'org_id' => (int)$conference['org_id'],
            'conference_id' => (int)$conference['id'],
            'committee_type' => trim((string)($_POST['committee_type'] ?? 'other')),
            'full_name_ar' => trim((string)($_POST['full_name_ar'] ?? '')),
            'full_name_en' => trim((string)($_POST['full_name_en'] ?? '')),
            'email' => trim((string)($_POST['email'] ?? '')),
            'affiliation_ar' => trim((string)($_POST['affiliation_ar'] ?? '')),
            'affiliation_en' => trim((string)($_POST['affiliation_en'] ?? '')),
            'role_title_ar' => trim((string)($_POST['role_title_ar'] ?? '')),
            'role_title_en' => trim((string)($_POST['role_title_en'] ?? '')),
            'image_path' => $imagePath,
            'sort_order' => (int)($_POST['sort_order'] ?? 0),
            'is_visible' => !empty($_POST['is_visible']) ? 1 : 0,
            'created_by' => (int)$_SESSION['user_id'],
        ]);

        header("Location: /easychair/admin/committee-images");
        exit;
    }

    public function deleteCommitteeImage()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/committee-images', 'delete'); }
        $conference = $this->conference();
        $this->deleteById('conference_committee_people', (int)($_GET['id'] ?? 0), $conference);
        header("Location: /easychair/admin/committee-images");
        exit;
    }

    public function reviewerAssignments()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/reviewer-assignments', 'view'); }
        $conference = $this->conference();

        $db = $this->db();

        $submissions = [];
        try {
            $stmt = $db->prepare("
                SELECT id, submission_no, title, title_ar, status, stage
                FROM submissions
                WHERE conference_id=? AND org_id=?
                ORDER BY id DESC
                LIMIT 500
            ");
            $stmt->execute([(int)$conference['id'], (int)$conference['org_id']]);
            $submissions = $stmt->fetchAll(\PDO::FETCH_ASSOC);
        } catch (\Throwable $e) {}

        $reviewers = [];
        try {
            $stmt = $db->prepare("
                SELECT DISTINCT u.id, u.email, u.first_name, u.last_name
                FROM users u
                LEFT JOIN user_conference_roles ucr ON ucr.user_id=u.id
                LEFT JOIN roles r ON r.id=ucr.role_id
                WHERE (ucr.conference_id=? OR u.org_id=?)
                  AND (r.code='reviewer' OR u.role='reviewer' OR u.email IS NOT NULL)
                ORDER BY u.email
                LIMIT 500
            ");
            $stmt->execute([(int)$conference['id'], (int)$conference['org_id']]);
            $reviewers = $stmt->fetchAll(\PDO::FETCH_ASSOC);
        } catch (\Throwable $e) {
            try {
                $reviewers = $db->query("SELECT id,email,first_name,last_name FROM users ORDER BY id DESC LIMIT 500")->fetchAll(\PDO::FETCH_ASSOC);
            } catch (\Throwable $e2) {}
        }

        $rows = [];
        try {
            $stmt = $db->prepare("
                SELECT ra.*, s.submission_no, s.title, s.title_ar, u.email, u.first_name, u.last_name
                FROM review_assignments ra
                LEFT JOIN submissions s ON s.id=ra.submission_id
                LEFT JOIN users u ON u.id=ra.reviewer_id
                WHERE ra.conference_id=? AND ra.org_id=?
                ORDER BY ra.id DESC
                LIMIT 500
            ");
            $stmt->execute([(int)$conference['id'], (int)$conference['org_id']]);
            $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);
        } catch (\Throwable $e) {}

        $this->view('reviewer_assignments', compact('conference','rows','submissions','reviewers'));
    }

    public function saveReviewerAssignment()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/reviewer-assignments', 'create'); }
        $conference = $this->conference();

        $this->insertDynamic('review_assignments', [
            'org_id' => (int)$conference['org_id'],
            'conference_id' => (int)$conference['id'],
            'submission_id' => (int)($_POST['submission_id'] ?? 0),
            'reviewer_id' => (int)($_POST['reviewer_id'] ?? 0),
            'status' => 'assigned',
            'due_date' => trim((string)($_POST['due_date'] ?? '')),
            'assigned_by' => (int)$_SESSION['user_id'],
            'created_by' => (int)$_SESSION['user_id'],
            'created_at' => date('Y-m-d H:i:s'),
        ]);

        header("Location: /easychair/admin/reviewer-assignments");
        exit;
    }

    public function deleteReviewerAssignment()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/reviewer-assignments', 'delete'); }
        $conference = $this->conference();
        $this->deleteById('review_assignments', (int)($_GET['id'] ?? 0), $conference);
        header("Location: /easychair/admin/reviewer-assignments");
        exit;
    }

    public function submissionStageRules()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/submission-stage-rules', 'view'); }
        $conference = $this->conference();

        $stmt = $this->db()->prepare("
            SELECT *
            FROM submission_stage_rules
            WHERE conference_id=? AND org_id=?
            ORDER BY sort_order, id
        ");
        $stmt->execute([(int)$conference['id'], (int)$conference['org_id']]);
        $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $this->view('submission_stage_rules', compact('conference','rows'));
    }

    public function saveSubmissionStageRule()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/submission-stage-rules', 'update'); }
        $conference = $this->conference();

        $stmt = $this->db()->prepare("
            INSERT INTO submission_stage_rules
            (org_id, conference_id, stage_key, stage_title_en, stage_title_ar, sort_order, allow_author_upload, notify_author, require_review_complete, is_active, created_by)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            ON DUPLICATE KEY UPDATE
                stage_title_en=VALUES(stage_title_en),
                stage_title_ar=VALUES(stage_title_ar),
                sort_order=VALUES(sort_order),
                allow_author_upload=VALUES(allow_author_upload),
                notify_author=VALUES(notify_author),
                require_review_complete=VALUES(require_review_complete),
                is_active=VALUES(is_active),
                updated_at=NOW()
        ");
        $stmt->execute([
            (int)$conference['org_id'],
            (int)$conference['id'],
            trim((string)($_POST['stage_key'] ?? '')),
            trim((string)($_POST['stage_title_en'] ?? '')),
            trim((string)($_POST['stage_title_ar'] ?? '')),
            (int)($_POST['sort_order'] ?? 0),
            !empty($_POST['allow_author_upload']) ? 1 : 0,
            !empty($_POST['notify_author']) ? 1 : 0,
            !empty($_POST['require_review_complete']) ? 1 : 0,
            !empty($_POST['is_active']) ? 1 : 0,
            (int)$_SESSION['user_id'],
        ]);

        header("Location: /easychair/admin/submission-stage-rules");
        exit;
    }

    public function deleteSubmissionStageRule()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/submission-stage-rules', 'delete'); }
        $conference = $this->conference();
        $this->deleteById('submission_stage_rules', (int)($_GET['id'] ?? 0), $conference);
        header("Location: /easychair/admin/submission-stage-rules");
        exit;
    }

    public function testEmail()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/test-email', 'view'); }
        if (function_exists('ec_require_action')) { ec_require_action('/easychair/admin/test-email', 'view'); }
        $conference = $this->conference();

        $stmt = $this->db()->prepare("
            SELECT *
            FROM conference_test_email_logs
            WHERE conference_id=? AND org_id=?
            ORDER BY id DESC
            LIMIT 100
        ");
        $stmt->execute([(int)$conference['id'], (int)$conference['org_id']]);
        $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $this->view('test_email', compact('conference','rows'));
    }

    public function sendTestEmail()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/test-email', 'create'); }
        if (function_exists('ec_require_action')) { ec_require_action('/easychair/admin/test-email', 'create'); }
        $conference = $this->conference();

        $to = trim((string)($_POST['recipient_email'] ?? ''));
        $subject = trim((string)($_POST['subject'] ?? 'EasyChair test email'));
        $body = trim((string)($_POST['body'] ?? 'This is a test email.'));

        $status = 'queued';
        $error = null;

        try {
            $this->insertDynamic('conference_mail_outbox', [
                'org_id' => (int)$conference['org_id'],
                'conference_id' => (int)$conference['id'],
                'template_key' => 'manual_test',
                'event_key' => 'manual_test',
                'recipient_email' => $to,
                'subject' => $subject,
                'body' => $body,
                'status' => 'queued',
                'created_by' => (int)$_SESSION['user_id'],
                'created_at' => date('Y-m-d H:i:s'),
            ]);
        } catch (\Throwable $e) {
            $status = 'failed';
            $error = $e->getMessage();
        }

        $this->insertDynamic('conference_test_email_logs', [
            'org_id' => (int)$conference['org_id'],
            'conference_id' => (int)$conference['id'],
            'recipient_email' => $to,
            'subject' => $subject,
            'body' => $body,
            'status' => $status,
            'error_message' => $error,
            'created_by' => (int)$_SESSION['user_id'],
        ]);

        header("Location: /easychair/admin/test-email");
        exit;
    }

    public function conferenceRolePermissions()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/conference-role-permissions', 'view'); }
        $conference = $this->conference();

        $roleCode = $this->role();

        if ($roleCode === 'super_admin') {
            $roles = $this->db()->query("SELECT id, code, name FROM roles ORDER BY code")->fetchAll(\PDO::FETCH_ASSOC);
            $menus = $this->db()->query("SELECT id, menu_key, label, label_ar, url, is_active FROM rbac_menu_items ORDER BY sort_order, id")->fetchAll(\PDO::FETCH_ASSOC);
        } else {
            $rolesStmt = $this->db()->prepare("
                SELECT id, code, name
                FROM roles
                WHERE code IN ('org_admin','admin','organizer','conference_chair','track_chair','section_editor','reviewer','author')
                ORDER BY code
            ");
            $rolesStmt->execute();
            $roles = $rolesStmt->fetchAll(\PDO::FETCH_ASSOC);

            $menusStmt = $this->db()->prepare("
                SELECT id, menu_key, label, label_ar, url, is_active
                FROM rbac_menu_items
                WHERE url <> '/easychair/admin/rbac-matrix'
                ORDER BY sort_order, id
            ");
            $menusStmt->execute();
            $menus = $menusStmt->fetchAll(\PDO::FETCH_ASSOC);
        }

        $stmt = $this->db()->prepare("
            SELECT *
            FROM rbac_role_menu_permissions
            WHERE conference_id=? AND org_id=?
        ");
        $stmt->execute([(int)$conference['id'], (int)$conference['org_id']]);
        $permissions = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $permissionMap = [];
        foreach ($permissions as $p) {
            $permissionMap[(int)$p['role_id']][(int)$p['menu_item_id']] = $p;
        }

        $this->view('conference_role_permissions', compact('conference','roles','menus','permissions','permissionMap'));
    }

    public function saveConferenceRolePermissions()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/conference-role-permissions', 'update'); }
        $conference = $this->conference();

        $roleId = (int)($_POST['role_id'] ?? 0);
        $items = $_POST['items'] ?? [];

        if ($roleId <= 0) {
            header("Location: /easychair/admin/conference-role-permissions");
            exit;
        }

        $roleStmt = $this->db()->prepare("SELECT code FROM roles WHERE id=? LIMIT 1");
        $roleStmt->execute([$roleId]);
        $targetRoleCode = (string)$roleStmt->fetchColumn();

        if ($this->role() !== 'super_admin' && $targetRoleCode === 'super_admin') {
            http_response_code(403);
            exit('Only super admin can manage super admin permissions.');
        }

        $menuRows = $this->db()->query("SELECT id, url FROM rbac_menu_items")->fetchAll(\PDO::FETCH_ASSOC);

        $upsert = $this->db()->prepare("
            INSERT INTO rbac_role_menu_permissions
            (org_id, conference_id, role_id, menu_item_id, is_allowed, can_view, can_create, can_update, can_delete, updated_by)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            ON DUPLICATE KEY UPDATE
                is_allowed=VALUES(is_allowed),
                can_view=VALUES(can_view),
                can_create=VALUES(can_create),
                can_update=VALUES(can_update),
                can_delete=VALUES(can_delete),
                updated_by=VALUES(updated_by),
                updated_at=NOW()
        ");

        foreach ($menuRows as $m) {
            $menuItemId = (int)$m['id'];
            $url = (string)($m['url'] ?? '');

            if ($url === '/easychair/admin/rbac-matrix' && $targetRoleCode !== 'super_admin') {
                $isAllowed = 0;
                $canView = 0;
                $canCreate = 0;
                $canUpdate = 0;
                $canDelete = 0;
            } else {
                $row = $items[$menuItemId] ?? [];
                $isAllowed = !empty($row['is_allowed']) ? 1 : 0;
                $canView = !empty($row['can_view']) ? 1 : 0;
                $canCreate = !empty($row['can_create']) ? 1 : 0;
                $canUpdate = !empty($row['can_update']) ? 1 : 0;
                $canDelete = !empty($row['can_delete']) ? 1 : 0;

                if (!$isAllowed) {
                    $canView = 0;
                    $canCreate = 0;
                    $canUpdate = 0;
                    $canDelete = 0;
                }
            }

            $upsert->execute([
                (int)$conference['org_id'],
                (int)$conference['id'],
                $roleId,
                $menuItemId,
                $isAllowed,
                $canView,
                $canCreate,
                $canUpdate,
                $canDelete,
                (int)$_SESSION['user_id'],
            ]);
        }

        header("Location: /easychair/admin/conference-role-permissions?role_id=" . $roleId);
        exit;
    }

    public function conferenceBusinessPermissions()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/conference-business-permissions', 'view'); }
        $conference = $this->conference();

        $stmt = $this->db()->prepare("
            SELECT *
            FROM conference_business_permissions
            WHERE conference_id=? AND org_id=?
            ORDER BY role_code, business_key
        ");
        $stmt->execute([(int)$conference['id'], (int)$conference['org_id']]);
        $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $this->view('conference_business_permissions', compact('conference','rows'));
    }

    public function saveConferenceBusinessPermission()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/conference-business-permissions', 'update'); }
        $conference = $this->conference();

        $stmt = $this->db()->prepare("
            INSERT INTO conference_business_permissions
            (org_id, conference_id, role_code, business_key, can_view, can_create, can_update, can_delete, created_by)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
            ON DUPLICATE KEY UPDATE
                can_view=VALUES(can_view),
                can_create=VALUES(can_create),
                can_update=VALUES(can_update),
                can_delete=VALUES(can_delete),
                updated_at=NOW()
        ");
        $stmt->execute([
            (int)$conference['org_id'],
            (int)$conference['id'],
            trim((string)($_POST['role_code'] ?? '')),
            trim((string)($_POST['business_key'] ?? '')),
            !empty($_POST['can_view']) ? 1 : 0,
            !empty($_POST['can_create']) ? 1 : 0,
            !empty($_POST['can_update']) ? 1 : 0,
            !empty($_POST['can_delete']) ? 1 : 0,
            (int)$_SESSION['user_id'],
        ]);

        header("Location: /easychair/admin/conference-business-permissions");
        exit;
    }

    public function deleteConferenceBusinessPermission()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/conference-business-permissions', 'delete'); }
        $conference = $this->conference();
        $this->deleteById('conference_business_permissions', (int)($_GET['id'] ?? 0), $conference);
        header("Location: /easychair/admin/conference-business-permissions");
        exit;
    }

    public function customRights()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/custom-rights', 'view'); }
        $conference = $this->conference();

        $stmt = $this->db()->prepare("
            SELECT *
            FROM conference_custom_rights
            WHERE conference_id=? AND org_id=?
            ORDER BY role_code, right_key
        ");
        $stmt->execute([(int)$conference['id'], (int)$conference['org_id']]);
        $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $this->view('custom_rights', compact('conference','rows'));
    }

    public function saveCustomRight()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/custom-rights', 'update'); }
        $conference = $this->conference();

        $stmt = $this->db()->prepare("
            INSERT INTO conference_custom_rights
            (org_id, conference_id, role_code, right_key, right_label_en, right_label_ar, is_allowed, notes, created_by)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
            ON DUPLICATE KEY UPDATE
                right_label_en=VALUES(right_label_en),
                right_label_ar=VALUES(right_label_ar),
                is_allowed=VALUES(is_allowed),
                notes=VALUES(notes),
                updated_at=NOW()
        ");
        $stmt->execute([
            (int)$conference['org_id'],
            (int)$conference['id'],
            trim((string)($_POST['role_code'] ?? '')),
            trim((string)($_POST['right_key'] ?? '')),
            trim((string)($_POST['right_label_en'] ?? '')),
            trim((string)($_POST['right_label_ar'] ?? '')),
            !empty($_POST['is_allowed']) ? 1 : 0,
            trim((string)($_POST['notes'] ?? '')),
            (int)$_SESSION['user_id'],
        ]);

        header("Location: /easychair/admin/custom-rights");
        exit;
    }

    public function deleteCustomRight()
    {
        $this->requireAccess();
        if (function_exists('ec_admin_require_url_action')) { ec_admin_require_url_action('/easychair/admin/custom-rights', 'delete'); }
        $conference = $this->conference();
        $this->deleteById('conference_custom_rights', (int)($_GET['id'] ?? 0), $conference);
        header("Location: /easychair/admin/custom-rights");
        exit;
    }
}
