<?php
namespace App\Controllers;

use App\Core\Database;
use App\Core\ConferenceMailer;
use App\Core\NotificationService;

class AdminSubmissionWorkflowController
{
    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 (!in_array($this->role(), ['super_admin','org_admin','admin','organizer','conference_chair','track_chair'], true)) {
            http_response_code(403);
            exit("Access denied.");
        }
    }

    private function columnExists(string $table, string $column): bool
    {
        $stmt = $this->db()->prepare("
            SELECT COUNT(*)
            FROM INFORMATION_SCHEMA.COLUMNS
            WHERE TABLE_SCHEMA=DATABASE()
              AND TABLE_NAME=?
              AND COLUMN_NAME=?
        ");
        $stmt->execute([$table, $column]);
        return (int)$stmt->fetchColumn() > 0;
    }

    private function submission(int $id): array
    {
        if ($id <= 0) {
            http_response_code(400);
            exit("Submission ID is required.");
        }

        $stmt = $this->db()->prepare("
            SELECT 
                s.*,
                c.short_name AS conference_short_name,
                c.slug AS conference_slug,
                c.org_id AS real_conference_org_id,
                o.name AS org_name,
                u.email AS author_email,
                CONCAT(COALESCE(u.first_name,''),' ',COALESCE(u.last_name,'')) AS author_name
            FROM submissions s
            LEFT JOIN conferences c ON c.id=s.conference_id
            LEFT JOIN organizations o ON o.id=s.org_id
            LEFT JOIN users u ON u.id=s.author_id
            WHERE s.id=?
            LIMIT 1
        ");
        $stmt->execute([$id]);
        $s = $stmt->fetch(\PDO::FETCH_ASSOC);

        if (!$s) {
            http_response_code(404);
            exit("Submission not found.");
        }

        /*
         * Superadmin can open any submission.
         * Other admin roles can open only submissions inside their own organization.
         */
        if ($this->role() !== 'super_admin') {
            $sessionOrg = (int)($_SESSION['org_id'] ?? 0);

            if ($sessionOrg <= 0 || (int)$s['org_id'] !== $sessionOrg) {
                http_response_code(403);
                exit("Invalid organization access.");
            }
        }

        /*
         * Important: resolve current context from the submission itself.
         * This avoids false 'Submission not found' when superadmin selected another conference.
         */
        $_SESSION['workflow_submission_conference_id'] = (int)$s['conference_id'];
        $_SESSION['workflow_submission_org_id'] = (int)$s['org_id'];

        return $s;
    }

    private function logActivity(array $submission, string $eventKey, string $title, string $body = ''): void
    {
        $stmt = $this->db()->prepare("
            INSERT INTO submission_activity_log
            (org_id, conference_id, submission_id, actor_id, actor_role, event_key, event_title, event_body)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?)
        ");
        $stmt->execute([
            (int)$submission['org_id'],
            (int)$submission['conference_id'],
            (int)$submission['id'],
            (int)$_SESSION['user_id'],
            $this->role(),
            $eventKey,
            $title,
            $body
        ]);
    }


    private function workflowEmailRule(array $submission, string $stage): ?array
    {
        $stmt = $this->db()->prepare("
            SELECT *
            FROM conference_workflow_email_rules
            WHERE conference_id=?
              AND org_id=?
              AND stage_key=?
              AND is_active=1
            LIMIT 1
        ");
        $stmt->execute([
            (int)$submission['conference_id'],
            (int)$submission['org_id'],
            $stage
        ]);
        $row = $stmt->fetch(\PDO::FETCH_ASSOC);

        return $row ?: null;
    }

    private function sendWorkflowNotification(array $submission, string $stage): void
    {
        $rule = $this->workflowEmailRule($submission, $stage);

        if (!$rule) {
            $this->logActivity(
                $submission,
                'workflow_email_skipped',
                'Workflow email skipped',
                "No active notification rule for stage: {$stage}"
            );
            return;
        }

        if (empty($submission['author_email'])) {
            $this->logActivity(
                $submission,
                'workflow_email_failed',
                'Workflow email failed',
                'Author email is missing.'
            );
            return;
        }

        $mailer = new ConferenceMailer();
        $result = $mailer->queueAndSend(
            (int)$submission['conference_id'],
            (int)$submission['org_id'],
            (int)$submission['id'],
            !empty($submission['author_id']) ? (int)$submission['author_id'] : null,
            (string)$rule['template_key'],
            (string)$submission['author_email'],
            trim((string)($submission['author_name'] ?? '')) ?: (string)$submission['author_email'],
            $this->templateVars($submission),
            (int)$_SESSION['user_id'],
            (string)($rule['lang'] ?? 'en')
        );

        if (!empty($result['ok'])) {
            $this->logActivity(
                $submission,
                'workflow_email_sent',
                'Workflow notification sent',
                "Stage: {$stage}\nTemplate: " . $rule['template_key'] . "\nOutbox ID: " . (int)$result['outbox_id']
            );

            $notifier = new NotificationService();
            $notifier->notifyAuthorWorkflow(
                $submission,
                'workflow_email_sent',
                'Workflow update: ' . $stage,
                'A workflow notification email was sent for your submission. Template: ' . $rule['template_key']
            );
        } else {
            $this->logActivity(
                $submission,
                'workflow_email_failed',
                'Workflow notification failed',
                "Stage: {$stage}\nTemplate: " . $rule['template_key'] . "\nError: " . ($result['error'] ?? '')
            );

            $notifier = new NotificationService();
            $notifier->notifyAuthorWorkflow(
                $submission,
                'workflow_email_failed',
                'Workflow update: ' . $stage,
                'A workflow update was made, but email delivery failed. Please check your workflow center.'
            );
        }
    }


    public function index()
    {
        $this->requireAccess();

        $submissionId = (int)($_GET['submission_id'] ?? 0);
        $submission = $this->submission($submissionId);

        $stmt = $this->db()->prepare("
            SELECT *
            FROM submission_versions
            WHERE submission_id=?
              AND org_id=?
              AND conference_id=?
            ORDER BY created_at DESC, id DESC
        ");
        $stmt->execute([(int)$submission['id'], (int)$submission['org_id'], (int)$submission['conference_id']]);
        $versions = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $stmt = $this->db()->prepare("
            SELECT 
                ra.*,
                u.email AS reviewer_email,
                CONCAT(COALESCE(u.first_name,''),' ',COALESCE(u.last_name,'')) AS reviewer_name
            FROM review_assignments ra
            LEFT JOIN users u ON u.id=ra.reviewer_id
            WHERE ra.submission_id=?
              AND ra.org_id=?
              AND ra.conference_id=?
            ORDER BY ra.id DESC
        ");
        $stmt->execute([(int)$submission['id'], (int)$submission['org_id'], (int)$submission['conference_id']]);
        $assignments = $stmt->fetchAll(\PDO::FETCH_ASSOC);

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

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

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

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

        $stageRules = [];
        $stmt = $this->db()->prepare("
            SELECT *
            FROM conference_submission_stage_rules
            WHERE conference_id=?
              AND org_id=?
            ORDER BY stage_key
        ");
        $stmt->execute([(int)$submission['conference_id'], (int)$submission['org_id']]);
        foreach ($stmt->fetchAll(\PDO::FETCH_ASSOC) as $r) {
            $stageRules[$r['stage_key']] = $r;
        }

        $stmt = $this->db()->prepare("
            SELECT *
            FROM conference_email_templates
            WHERE conference_id=?
              AND org_id=?
              AND is_active=1
            ORDER BY template_key, event_key
        ");
        $stmt->execute([(int)$submission['conference_id'], (int)$submission['org_id']]);
        $emailTemplates = $stmt->fetchAll(\PDO::FETCH_ASSOC);

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

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

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

    public function updateStatus()
    {
        $this->requireAccess();

        $submissionId = (int)($_POST['submission_id'] ?? 0);
        $submission = $this->submission($submissionId);

        $status = trim($_POST['status'] ?? '');
        $stage = trim($_POST['stage'] ?? '');
        $productionStatus = trim($_POST['production_status'] ?? 'pending');
        $decision = trim($_POST['decision'] ?? '');
        $notes = trim($_POST['decision_notes'] ?? '');

        $allowedStages = [
            'submitted','screening','reviewing','rebuttal','revision_required',
            'revision_submitted','accepted','rejected','camera_ready',
            'production','galley','assigned_to_issue','issue','published'
        ];

        if (!in_array($stage, $allowedStages, true)) {
            exit("Invalid stage.");
        }

        if ($status === '') {
            $status = $stage;
        }

        $sets = [];
        $params = [];

        foreach ([
            'status' => $status,
            'stage' => $stage,
            'production_status' => $productionStatus,
            'decision' => $decision,
            'decision_notes' => $notes,
        ] as $col => $val) {
            if ($this->columnExists('submissions', $col)) {
                $sets[] = "{$col}=?";
                $params[] = $val;
            }
        }

        if ($stage === 'published' && $this->columnExists('submissions', 'published_at')) {
            $sets[] = "published_at=COALESCE(published_at,NOW())";
        }

        if ($this->columnExists('submissions', 'updated_at')) {
            $sets[] = "updated_at=NOW()";
        }

        if (!$sets) {
            exit("No updateable columns found.");
        }

        $params[] = (int)$submission['id'];
        $params[] = (int)$submission['conference_id'];
        $params[] = (int)$submission['org_id'];

        $stmt = $this->db()->prepare("
            UPDATE submissions
            SET " . implode(',', $sets) . "
            WHERE id=?
              AND conference_id=?
              AND org_id=?
        ");
        $stmt->execute($params);

        $body = "Status: {$submission['status']} -> {$status}\nStage: {$submission['stage']} -> {$stage}\nProduction: " . ($submission['production_status'] ?? '') . " -> {$productionStatus}\nNotes: {$notes}";
        $this->logActivity($submission, 'admin_status_updated', 'Submission workflow updated', $body);

        $notifier = new NotificationService();
        $notifier->notifyAuthorWorkflow(
            $submission,
            'admin_status_updated',
            'Submission workflow updated',
            "Your submission status was updated to: {$status} / {$stage}"
        );

        if (!empty($_POST['send_workflow_email'])) {
            $fresh = $this->submission((int)$submission['id']);
            $this->sendWorkflowNotification($fresh, $stage);
        }

        header("Location: /easychair/admin/submission-workflow?submission_id=" . (int)$submission['id']);
        exit;
    }

    private function templateVars(array $submission): array
    {
        $conferenceTitle = ($submission['conference_short_name'] ?? '') ?: ('Conference #' . ($submission['conference_id'] ?? ''));
        $submissionTitle = ($submission['title'] ?? '') ?: (($submission['title_en'] ?? '') ?: (($submission['title_ar'] ?? '') ?: ('Submission #' . ($submission['id'] ?? ''))));

        return [
            'author_name' => trim((string)($submission['author_name'] ?? '')) ?: (string)($submission['author_email'] ?? ''),
            'author_email' => (string)($submission['author_email'] ?? ''),
            'submission_no' => (string)($submission['submission_no'] ?? ('#' . ($submission['id'] ?? ''))),
            'submission_title' => $submissionTitle,
            'decision_notes' => (string)($submission['decision_notes'] ?? ''),
            'conference_title' => $conferenceTitle,
            'conference_short_name' => (string)($submission['conference_short_name'] ?? $conferenceTitle),
            'login_link' => 'https://www.jpu.edu.jo/easychair/login',
            'workflow_link' => 'https://www.jpu.edu.jo/easychair/author/workflow?submission_id=' . (int)($submission['id'] ?? 0),
        ];
    }

    public function sendTemplateEmail()
    {
        $this->requireAccess();

        $submissionId = (int)($_POST['submission_id'] ?? 0);
        $templateKey = trim((string)($_POST['template_key'] ?? ''));
        $lang = trim((string)($_POST['lang'] ?? 'en'));

        if ($templateKey === '') {
            exit("Template key is required.");
        }

        if (!in_array($lang, ['en','ar'], true)) {
            $lang = 'en';
        }

        $submission = $this->submission($submissionId);

        if (empty($submission['author_email'])) {
            exit("Author email not found.");
        }

        /*
         * Refresh submission after workflow update if needed.
         */
        $fresh = $this->submission($submissionId);

        $mailer = new ConferenceMailer();
        $result = $mailer->queueAndSend(
            (int)$fresh['conference_id'],
            (int)$fresh['org_id'],
            (int)$fresh['id'],
            !empty($fresh['author_id']) ? (int)$fresh['author_id'] : null,
            $templateKey,
            (string)$fresh['author_email'],
            trim((string)$fresh['author_name']) ?: (string)$fresh['author_email'],
            $this->templateVars($fresh),
            (int)$_SESSION['user_id'],
            $lang
        );

        if (!empty($result['ok'])) {
            $this->logActivity(
                $fresh,
                'email_sent',
                'Email sent to author',
                "Template: {$templateKey}\nOutbox ID: " . (int)$result['outbox_id']
            );
        } else {
            $this->logActivity(
                $fresh,
                'email_failed',
                'Email failed',
                "Template: {$templateKey}\nOutbox ID: " . (int)($result['outbox_id'] ?? 0) . "\nError: " . ($result['error'] ?? '')
            );
        }

        header("Location: /easychair/admin/submission-workflow?submission_id=" . (int)$fresh['id'] . "&email_sent=" . (!empty($result['ok']) ? '1' : '0'));
        exit;
    }


}