<?php
namespace App\Controllers;

use App\Core\Database;

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

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

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

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

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

        $role = $_SESSION['conference_role'] ?? $_SESSION['role'] ?? $_SESSION['user_role'] ?? '';

        if ($role !== 'author') {
            http_response_code(403);
            exit("Author access required.");
        }
    }

    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 ((int)$c['org_id'] !== (int)($_SESSION['org_id'] ?? 0)) {
            http_response_code(403);
            exit("Invalid organization access.");
        }

        return $c;
    }

    private function submission(int $id): array
    {
        $stmt = $this->db()->prepare("
            SELECT *
            FROM submissions
            WHERE id=?
              AND author_id=?
              AND conference_id=?
              AND org_id=?
            LIMIT 1
        ");
        $stmt->execute([
            $id,
            (int)$_SESSION['user_id'],
            (int)$_SESSION['conference_id'],
            (int)$_SESSION['org_id']
        ]);

        $s = $stmt->fetch(\PDO::FETCH_ASSOC);

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

        return $s;
    }

    private function stageRule(array $submission): array
    {
        $stage = (string)($submission['stage'] ?? $submission['status'] ?? 'submitted');

        $stmt = $this->db()->prepare("
            SELECT *
            FROM conference_submission_stage_rules
            WHERE conference_id=?
              AND org_id=?
              AND stage_key=?
            LIMIT 1
        ");
        $stmt->execute([
            (int)$submission['conference_id'],
            (int)$submission['org_id'],
            $stage
        ]);

        $rule = $stmt->fetch(\PDO::FETCH_ASSOC);

        if (!$rule) {
            return [
                'allow_author_update' => 0,
                'allow_author_file_upload' => 0,
                'allow_rebuttal' => 0,
                'allow_camera_ready' => 0,
                'visible_reviews_to_author' => 0,
            ];
        }

        return $rule;
    }

    private function nextVersionNo(int $submissionId, string $uploadType): int
    {
        $stmt = $this->db()->prepare("
            SELECT COALESCE(MAX(version_no),0) + 1
            FROM submission_versions
            WHERE submission_id=?
              AND upload_type=?
        ");
        $stmt->execute([$submissionId, $uploadType]);
        return (int)$stmt->fetchColumn();
    }

    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'],
            'author',
            $eventKey,
            $title,
            $body
        ]);
    }

    private function uploadFile(array $submission, string $uploadType): array
    {
        if (empty($_FILES['file']['name']) || !is_uploaded_file($_FILES['file']['tmp_name'])) {
            exit("File is required.");
        }

        $allowedExt = ['pdf','doc','docx','zip','png','jpg','jpeg','xlsx','xls','ppt','pptx'];
        $ext = strtolower(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION));
        $ext = preg_replace('/[^a-z0-9]/', '', $ext);

        if (!in_array($ext, $allowedExt, true)) {
            exit("Invalid file type.");
        }

        $dir = BASE_PATH . '/public/storage/submissions/' . (int)$submission['conference_id'] . '/' . (int)$submission['id'];

        if (!is_dir($dir)) {
            mkdir($dir, 0775, true);
        }

        $file = $uploadType . '_' . (int)$_SESSION['user_id'] . '_' . date('YmdHis') . '_' . rand(1000,9999) . '.' . $ext;

        if (!move_uploaded_file($_FILES['file']['tmp_name'], $dir . '/' . $file)) {
            exit("Could not upload file.");
        }

        return [
            'path' => 'submissions/' . (int)$submission['conference_id'] . '/' . (int)$submission['id'] . '/' . $file,
            'original' => $_FILES['file']['name']
        ];
    }

    public function index()
    {
        $this->requireAuthor();
        $conference = $this->conference();

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

        $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 *
            FROM author_rebuttals
            WHERE submission_id=?
              AND author_id=?
              AND org_id=?
              AND conference_id=?
            ORDER BY id DESC
        ");
        $stmt->execute([
            (int)$submission['id'],
            (int)$_SESSION['user_id'],
            (int)$submission['org_id'],
            (int)$submission['conference_id']
        ]);
        $rebuttals = $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 100
        ");
        $stmt->execute([(int)$submission['id'], (int)$submission['org_id'], (int)$submission['conference_id']]);
        $activity = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $reviews = [];
        if (!empty($rule['visible_reviews_to_author'])) {
            $stmt = $this->db()->prepare("
                SELECT 
                    rv.*,
                    ra.id AS assignment_id
                FROM reviews rv
                LEFT JOIN review_assignments ra 
                       ON ra.id = COALESCE(rv.assignment_id, rv.review_assignment_id)
                WHERE rv.submission_id=?
                  AND rv.org_id=?
                  AND rv.conference_id=?
                ORDER BY rv.id DESC
            ");
            $stmt->execute([(int)$submission['id'], (int)$submission['org_id'], (int)$submission['conference_id']]);
            $reviews = $stmt->fetchAll(\PDO::FETCH_ASSOC);
        }

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

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

    public function uploadRevision()
    {
        $this->requireAuthor();
        $submission = $this->submission((int)($_POST['submission_id'] ?? 0));
        $rule = $this->stageRule($submission);

        if (empty($rule['allow_author_file_upload'])) {
            http_response_code(403);
            exit("Revision upload is not allowed at this stage.");
        }

        $upload = $this->uploadFile($submission, 'revision');
        $versionNo = $this->nextVersionNo((int)$submission['id'], 'revision');

        $stmt = $this->db()->prepare("
            INSERT INTO submission_versions
            (org_id, conference_id, submission_id, version_no, upload_type, file_path, original_filename, uploaded_by, notes)
            VALUES (?, ?, ?, ?, 'revision', ?, ?, ?, ?)
        ");
        $stmt->execute([
            (int)$submission['org_id'],
            (int)$submission['conference_id'],
            (int)$submission['id'],
            $versionNo,
            $upload['path'],
            $upload['original'],
            (int)$_SESSION['user_id'],
            trim($_POST['notes'] ?? '')
        ]);

        $stmt = $this->db()->prepare("
            UPDATE submissions
            SET status='revision_submitted',
                stage='reviewing',
                updated_at=NOW()
            WHERE id=?
        ");
        $stmt->execute([(int)$submission['id']]);

        $this->logActivity($submission, 'revision_uploaded', 'Revision uploaded', $upload['original']);

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

    public function uploadCameraReady()
    {
        $this->requireAuthor();
        $submission = $this->submission((int)($_POST['submission_id'] ?? 0));
        $rule = $this->stageRule($submission);

        if (empty($rule['allow_camera_ready'])) {
            http_response_code(403);
            exit("Camera-ready upload is not allowed at this stage.");
        }

        $upload = $this->uploadFile($submission, 'camera_ready');
        $versionNo = $this->nextVersionNo((int)$submission['id'], 'camera_ready');

        $stmt = $this->db()->prepare("
            INSERT INTO submission_versions
            (org_id, conference_id, submission_id, version_no, upload_type, file_path, original_filename, uploaded_by, notes)
            VALUES (?, ?, ?, ?, 'camera_ready', ?, ?, ?, ?)
        ");
        $stmt->execute([
            (int)$submission['org_id'],
            (int)$submission['conference_id'],
            (int)$submission['id'],
            $versionNo,
            $upload['path'],
            $upload['original'],
            (int)$_SESSION['user_id'],
            trim($_POST['notes'] ?? '')
        ]);

        $stmt = $this->db()->prepare("
            UPDATE submissions
            SET status='camera_ready',
                stage='production',
                production_status='camera_ready_uploaded',
                updated_at=NOW()
            WHERE id=?
        ");
        $stmt->execute([(int)$submission['id']]);

        $this->logActivity($submission, 'camera_ready_uploaded', 'Camera-ready uploaded', $upload['original']);

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

    public function submitRebuttal()
    {
        $this->requireAuthor();
        $submission = $this->submission((int)($_POST['submission_id'] ?? 0));
        $rule = $this->stageRule($submission);

        if (empty($rule['allow_rebuttal'])) {
            http_response_code(403);
            exit("Rebuttal is not allowed at this stage.");
        }

        $text = trim($_POST['rebuttal_text'] ?? '');

        if ($text === '') {
            exit("Rebuttal text is required.");
        }

        $stmt = $this->db()->prepare("
            INSERT INTO author_rebuttals
            (org_id, conference_id, submission_id, author_id, rebuttal_text, status)
            VALUES (?, ?, ?, ?, ?, 'submitted')
        ");
        $stmt->execute([
            (int)$submission['org_id'],
            (int)$submission['conference_id'],
            (int)$submission['id'],
            (int)$_SESSION['user_id'],
            $text
        ]);

        $this->logActivity($submission, 'author_rebuttal_submitted', 'Author rebuttal submitted', mb_substr($text, 0, 250));

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