<?php
declare(strict_types=1);

namespace App\Controllers;

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

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

use App\Core\Controller;
use App\Core\Database;
use App\Services\TrackChairScope;

final class AdminReviewerAssignmentsController extends Controller
{
    private function cid($db): int
{
    $orgId = (int) current_org_id();

    $cid = function_exists('default_conference_id')
        ? (int) default_conference_id()
        : 0;

    if ($cid > 0) {
        return $cid;
    }

    return (int)(
        $db->query("
            SELECT id
            FROM conferences
            WHERE
                (
                    is_active = 1
                    OR is_active IS NULL
                )
                AND org_id = " . (int)$orgId . "
            ORDER BY id DESC
            LIMIT 1
        ")->fetchColumn()
        ?: 0
    );
}
    public function index(): void
    {
//        require_admin_area();
  
    if(empty($_SESSION['user_id'])){
        header('Location:/easychair/login');
        exit;
    }
      $orgId = (int) current_org_id();

        $db=Database::getInstance();
        $cid=$this->cid($db);

        [$trackSql,$trackParams] =
    TrackChairScope::sql('');

$subsSql="
SELECT
s.id,
s.title_en,
s.title_ar,
s.status,
s.track_id,

COALESCE(
    t.name_en,
    t.name_ar,
    CONCAT('Track #',s.track_id)
) AS track_name

FROM submissions s

LEFT JOIN tracks t
ON t.id=s.track_id

WHERE s.conference_id=?
{$trackSql}
AND s.conference_id IN
(
    SELECT id
    FROM conferences
    WHERE org_id=".(int)$orgId."
)
ORDER BY s.id DESC
LIMIT 300
";

$subs=$db->prepare($subsSql);

$params=[
$cid
];

$params=array_merge(
    $params,
    $trackParams
);

$subs->execute($params);

$submissions=
$subs->fetchAll()
?:[];

error_log(
'PACK831_SUBMISSIONS='.
json_encode([
'count'=>count($submissions),
'ids'=>array_column($submissions,'id')
])
);


error_log(
'TRACK_CHAIR_SUBMISSIONS='.
count($submissions)
);

        //$revs=$db->query("SELECT id,email FROM users WHERE role_id=4 AND is_active=1 ORDER BY id DESC LIMIT 1000")->fetchAll()?:[];

$revsStmt = $db->prepare("
    SELECT DISTINCT
        u.id,
        u.email,
        u.first_name,
        u.last_name
    FROM conference_user_roles cur

    INNER JOIN users u
        ON u.id = cur.user_id

    WHERE cur.role_code = 'reviewer'

    AND cur.conference_id = :c

    AND (
        cur.org_id = :o
        OR cur.org_id IS NULL
    )

    AND u.is_active = 1

    ORDER BY
        u.first_name ASC,
        u.last_name ASC,
        u.id DESC

    LIMIT 1000
");

$revsStmt->execute([
    ':c' => $cid,
    ':o' => $orgId
]);

$revs = $revsStmt->fetchAll() ?: [];

/*
--------------------------------------------------
PACK823A
REVIEWER EXPERTISE RANKING
--------------------------------------------------
*/

foreach ($revs as &$r) {

    $exp =
        strtolower(
            (string)(
                $r["expertise"]
                ?? ""
            )
        );

    $score = 0;

    if (
        str_contains($exp,"ai")
        ||
        str_contains($exp,"artificial intelligence")
    ) {
        $score += 100;
    }

    if (
        str_contains($exp,"cyber")
        ||
        str_contains($exp,"security")
    ) {
        $score += 90;
    }

    if (
        str_contains($exp,"software")
    ) {
        $score += 80;
    }

    if (
        str_contains($exp,"data science")
    ) {
        $score += 70;
    }

    if (
        str_contains($exp,"network")
    ) {
        $score += 60;
    }

    $r["expertise_score"] =
        $score;
}

unset($r);

/*
--------------------------------------------------
PACK824A
REVIEWER WORKLOAD
--------------------------------------------------
*/

try {

    $loadStmt = $db->query("
        SELECT
            reviewer_id,
            COUNT(*) active_assignments
        FROM review_assignments
        WHERE status IN
        (
            'assigned',
            'accepted'
        )
        GROUP BY reviewer_id
    ");

    $loads = [];

    foreach(
        $loadStmt->fetchAll(PDO::FETCH_ASSOC)
        as $row
    ){

        $loads[
            (int)$row['reviewer_id']
        ] =
            (int)$row['active_assignments'];

    }

} catch (\Throwable $e) {

    $loads = [];

}

/*
--------------------------------------------------
PACK825A
REVIEWER RELIABILITY
--------------------------------------------------
*/

$completionStats = [];

try {

    $compStmt = $db->query("
        SELECT
            reviewer_id,
            COUNT(*) total_assignments,
            SUM(
                CASE
                    WHEN status='completed'
                    THEN 1
                    ELSE 0
                END
            ) completed_assignments
        FROM review_assignments
        GROUP BY reviewer_id
    ");

    foreach(
        $compStmt->fetchAll(PDO::FETCH_ASSOC)
        as $row
    ){

        $completionStats[
            (int)$row['reviewer_id']
        ] = $row;

    }

} catch (\Throwable $e) {}

/*
--------------------------------------------------
PACK826
TRACK EXPERIENCE + REVIEW QUALITY
--------------------------------------------------
*/

$trackHistory = [];
$reviewQuality = [];

/*
--------------------------------------------------
PACK830
SUBMISSION TRACK MAP
--------------------------------------------------
*/

$submissionTracks = [];

foreach($submissions as $sx){

    $submissionTracks[
        (int)$sx['id']
    ] = (int)(
        $sx['track_id']
        ??
        0
    );

}

try {

    $stmtTH = $db->query("
        SELECT
            ra.reviewer_id,
            s.track_id,
            COUNT(*) completed_reviews
        FROM review_assignments ra
        JOIN submissions s
            ON s.id = ra.submission_id
        WHERE ra.status='completed'
        GROUP BY
            ra.reviewer_id,
            s.track_id
    ");

    foreach(
        $stmtTH->fetchAll(PDO::FETCH_ASSOC)
        as $row
    ){

        $trackHistory[
            (int)$row['reviewer_id']
        ][
            (int)$row['track_id']
        ] =
            (int)$row['completed_reviews'];

    }

} catch (\Throwable $e) {}

try {

    $stmtRQ = $db->query("
        SELECT
            reviewer_id,
            AVG(
                COALESCE(
                    overall_score,
                    score,
                    0
                )
            ) avg_quality
        FROM reviews
        GROUP BY reviewer_id
    ");

    foreach(
        $stmtRQ->fetchAll(PDO::FETCH_ASSOC)
        as $row
    ){

        $reviewQuality[
            (int)$row['reviewer_id']
        ] =
            (float)$row['avg_quality'];

    }

} catch (\Throwable $e) {}

foreach($revs as &$r){

    $rid =
        (int)$r['id'];

    $active =
        (int)(
            $loads[$rid]
            ??
            0
        );

    $total =
        (int)(
            $completionStats[$rid]['total_assignments']
            ??
            0
        );

    $completed =
        (int)(
            $completionStats[$rid]['completed_assignments']
            ??
            0
        );

    $completionRate =
        $total > 0
        ? round(
            ($completed / $total) * 100
          )
        : 0;

    $r['active_assignments'] =
        $active;

    $r['completion_rate'] =
        $completionRate;

    $submissionTrack = 0;

    $trackExperience =
        (int)(
            $trackHistory[$rid][$submissionTrack]
            ??
            0
        );

    $quality =
        (float)(
            $reviewQuality[$rid]
            ??
            0
        );

    $r['track_experience'] =
        $trackExperience;

    $r['review_quality'] =
        round($quality,2);

    $r['final_score'] =
        (int)(
            ($r['expertise_score'] ?? 0)
            -
            ($active * 10)
            +
            ($completionRate * 0.5)
            +
            ($trackExperience * 5)
            +
            ($quality * 2)
        );

}

unset($r);

usort(
    $revs,
    function($a,$b){

        return
            ($b['final_score'] ?? 0)
            <=>
            ($a['final_score'] ?? 0);

    }
);

        
$ra=$db->prepare("

SELECT
ra.*,
u.email,
u.first_name,
u.last_name,
COALESCE(
s.title_en,
s.title_ar,
CONCAT('Submission #',s.id)
) AS title

FROM review_assignments ra

LEFT JOIN users u
ON u.id=ra.reviewer_id

LEFT JOIN submissions s
ON s.id=ra.submission_id

WHERE
ra.conference_id=:c
{$trackSql}

ORDER BY
ra.id DESC

LIMIT 500

");

$ra->execute([
':c'=>$cid
]);

$assignments=
$ra->fetchAll(
\PDO::FETCH_ASSOC
)
?:[];

error_log(
'PACK831_ASSIGNMENTS='.
count($assignments)
);


/*
--------------------------------------------------
PACK839A
REVIEWER SLA METRICS
--------------------------------------------------
*/

try{

    $pendingReviews=
    (int)$db->query("
        SELECT COUNT(*)
        FROM review_assignments
        WHERE status IN
        (
            'assigned',
            'accepted'
        )
    ")->fetchColumn();

}catch(Throwable $e){

    $pendingReviews=0;

}

try{

    $overdueReviews=
    (int)$db->query("
        SELECT COUNT(*)
        FROM review_assignments
        WHERE status IN
        (
            'assigned',
            'accepted'
        )
        AND DATEDIFF(
            NOW(),
            assigned_at
        ) >= 14
    ")->fetchColumn();

}catch(Throwable $e){

    $overdueReviews=0;

}

try{

    $criticalReviews=
    (int)$db->query("
        SELECT COUNT(*)
        FROM review_assignments
        WHERE status IN
        (
            'assigned',
            'accepted'
        )
        AND DATEDIFF(
            NOW(),
            assigned_at
        ) >= 21
    ")->fetchColumn();

}catch(Throwable $e){

    $criticalReviews=0;

}

try{

    $remindersSent=
    (int)$db->query("
        SELECT COUNT(*)
        FROM review_assignment_reminders
    ")->fetchColumn();

}catch(Throwable $e){

    $remindersSent=0;

}

foreach($assignments as &$a){

    $assignedTs=
    strtotime(
        $a['assigned_at']
        ??
        $a['created_at']
        ??
        'now'
    );

    $a['age_days']=
    max(
        0,
        (int)floor(
            (time()-$assignedTs)/86400
        )
    );
}
unset($a);


$this->view(
'admin/reviewer_assignments/index',
[
'submissions'=>$submissions,
'subs'=>$submissions,

'reviewers'=>$revs,
'revs'=>$revs,

'assignments'=>$assignments,
'rows'=>$assignments,

'pendingReviews'=>$pendingReviews,
'overdueReviews'=>$overdueReviews,
'criticalReviews'=>$criticalReviews,
'remindersSent'=>$remindersSent,

'group'=>[]
]
);
    }

    public function assign(): void
    {
     //   require_admin_area();
       
    if(empty($_SESSION['user_id'])){
        header('Location:/easychair/login');
        exit;
    }
 csrf_check();

        $db=Database::getInstance();

        $sid=(int)($_POST['submission_id']??0);
        $rid=(int)($_POST['reviewer_id']??0);
        $round=max(1,(int)($_POST['round_no']??1));

        if(!$sid||!$rid){
            header('Location: '.base_path('admin/reviewer-assignments'));
            exit;
        }

        $cid=$this->cid($db);

/*
--------------------------------------------------
PACK821A
TRACK CHAIR ASSIGNMENT SCOPE
--------------------------------------------------
*/

$isTrackChair =
    TrackChairScope::isTrackChair();

if ($isTrackChair) {

    $trackIds =
        TrackChairScope::trackIds();

    $stmtTrack =
        $db->prepare("
            SELECT track_id
            FROM submissions
            WHERE id=?
            LIMIT 1
        ");

    $stmtTrack->execute([$sid]);

    $submissionTrackId =
        (int)$stmtTrack->fetchColumn();

    if (
        !$trackIds
        ||
        !in_array(
            $submissionTrackId,
            $trackIds,
            true
        )
    ) {

        die(
            "Track scope violation"
        );
    }
}

        $orgId=function_exists('current_org_id')
            ? (int)current_org_id()
            : 0;

        $uid=(int)($_SESSION['user_id']??0);

/*
--------------------------------------------------
PACK828
CONFLICT DETECTION
--------------------------------------------------
*/

/* duplicate assignment */

$dup=$db->prepare("
SELECT id
FROM review_assignments
WHERE submission_id=?
AND reviewer_id=?
LIMIT 1
");

$dup->execute([
    $sid,
    $rid
]);

if($dup->fetchColumn()){

    $_SESSION['toast']=[
        'type'=>'warning',
        'msg'=>'Reviewer already assigned'
    ];

    header(
    'Location: '.base_path('admin/reviewer-assignments')
    );
    exit;
}

/* author check */

$authorStmt=$db->prepare("
SELECT author_id
FROM submissions
WHERE id=?
LIMIT 1
");

$authorStmt->execute([
    $sid
]);

$authorId=
(int)$authorStmt->fetchColumn();

if(
    $authorId>0
    &&
    $authorId==$rid
){

    $_SESSION['toast']=[
        'type'=>'danger',
        'msg'=>'Reviewer cannot review own submission'
    ];

    header(
    'Location: '.base_path('admin/reviewer-assignments')
    );
    exit;
}

/* email domain warning */

try{

    $dom=$db->prepare("
    SELECT

    au.email author_email,
    ru.email reviewer_email

    FROM submissions s

    LEFT JOIN users au
    ON au.id=s.author_id

    LEFT JOIN users ru
    ON ru.id=?

    WHERE s.id=?
    LIMIT 1
    ");

    $dom->execute([
        $rid,
        $sid
    ]);

    $d=
    $dom->fetch(PDO::FETCH_ASSOC);

    if(
        !empty($d['author_email'])
        &&
        !empty($d['reviewer_email'])
    ){

        $a=
        strtolower(
            substr(
                strrchr(
                    $d['author_email'],
                    '@'
                ),
                1
            )
        );

        $r=
        strtolower(
            substr(
                strrchr(
                    $d['reviewer_email'],
                    '@'
                ),
                1
            )
        );

        if(
            $a
            &&
            $r
            &&
            $a==$r
        ){

            error_log(
                'PACK828 SAME DOMAIN WARNING: '
                .$d['author_email']
                .' <-> '
                .$d['reviewer_email']
            );

        }

    }

}catch(Throwable $e){}

/* workload warning */

try{

    $load=$db->prepare("
    SELECT COUNT(*)
    FROM review_assignments
    WHERE reviewer_id=?
    AND status IN
    (
        'assigned',
        'accepted'
    )
    ");

    $load->execute([
        $rid
    ]);

    $active=
    (int)$load->fetchColumn();

    if($active>=10){

        error_log(
            'PACK828 HIGH LOAD WARNING reviewer='
            .$rid
            .' active='
            .$active
        );

    }

}catch(Throwable $e){}

        $sql="
INSERT IGNORE INTO review_assignments
(
submission_id,
reviewer_id,
conference_id,
org_id,
assigned_by,
round_no,
status
)
VALUES
(
:s,
:r,
:c,
:o,
:u,
:n,
'pending'
)
";

        $db->prepare($sql)->execute([
            ':s'=>$sid,
            ':r'=>$rid,
            ':c'=>$cid,
            ':o'=>$orgId,
            ':u'=>$uid,
            ':n'=>$round
        ]);

        header('Location: '.base_path('admin/reviewer-assignments'));
        exit;
    }

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

    $id=(int)($_GET['id'] ?? 0);

    if(!$id){
        header(
        'Location: '.base_path('admin/reviewer-assignments')
        );
        exit;
    }

    $db=\App\Core\Database::getInstance();

    /*
    |------------------------------------------------------------
    | LOAD ASSIGNMENT + REVIEWER + SUBMISSION + CONFERENCE
    | BEFORE DELETE
    |------------------------------------------------------------
    */

    $stmt=$db->prepare("
        SELECT
            ra.*,

            u.email,
            u.first_name,
            u.last_name,
            u.preferred_lang,

            s.title_en,
            s.title_ar,

            c.title_en AS conference_title_en,
            c.title_ar AS conference_title_ar

        FROM review_assignments ra

        LEFT JOIN users u
            ON u.id=ra.reviewer_id

        LEFT JOIN submissions s
            ON s.id=ra.submission_id

        LEFT JOIN conferences c
            ON c.id=ra.conference_id

        WHERE ra.id=?
        LIMIT 1
    ");

    $stmt->execute([$id]);

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

    if(!$a){
        header(
        'Location: '.base_path('admin/reviewer-assignments')
        );
        exit;
    }


/*
--------------------------------------------------
PACK822A
TRACK CHAIR UNASSIGN SCOPE
--------------------------------------------------
*/

$isTrackChair =
    TrackChairScope::isTrackChair();

if ($isTrackChair) {

    $trackIds =
        TrackChairScope::trackIds();

    $stmtTrack =
        $db->prepare("
            SELECT track_id
            FROM submissions
            WHERE id=?
            LIMIT 1
        ");

    $stmtTrack->execute([
        (int)$a["submission_id"]
    ]);

    $submissionTrackId =
        (int)$stmtTrack->fetchColumn();

    if (
        !$trackIds
        ||
        !in_array(
            $submissionTrackId,
            $trackIds,
            true
        )
    ) {

        die("Track scope violation");
    }
}

    $submissionId=
    (int)$a['submission_id'];

    /*
    |------------------------------------------------------------
    | DELETE ASSIGNMENT
    |------------------------------------------------------------
    */

    $db->prepare("
        DELETE
        FROM review_assignments
        WHERE id=?
    ")->execute([$id]);

    /*
    |------------------------------------------------------------
    | CHECK REMAINING REVIEWERS
    |------------------------------------------------------------
    */

    $stmt=$db->prepare("
        SELECT COUNT(*)
        FROM review_assignments
        WHERE submission_id=?
    ");

    $stmt->execute([$submissionId]);

    $remaining=
    (int)$stmt->fetchColumn();

    if($remaining<=0){

        $db->prepare("
            UPDATE submissions
            SET
                status='submitted',
                stage='submission',
                updated_at=NOW()
            WHERE id=?
        ")->execute([
            $submissionId
        ]);
    }

    /*
    |------------------------------------------------------------
    | WORKFLOW LOG
    |------------------------------------------------------------
    */

    if(
        class_exists(
        \App\Services\SubmissionWorkflowService::class
        )
    ){

        \App\Services\SubmissionWorkflowService::log(
            $submissionId,
            'reviewer_unassigned',
            'Reviewer Unassigned',
            'Reviewer removed from submission.',
            $_SESSION['user_id'] ?? null,
            $_SESSION['role'] ?? null
        );

        /*
        |--------------------------------------------------------
        | EMAIL REVIEWER
        |--------------------------------------------------------
        */

        try{

            \App\Services\SubmissionWorkflowService::queueEmail(

                (int)($a['conference_id'] ?? 0),

                'reviewer_unassigned',

                (string)($a['email'] ?? ''),

                trim(
                    ($a['first_name'] ?? '')
                    .' '.
                    ($a['last_name'] ?? '')
                ),

                [

                    'reviewer_name'=>
                    trim(
                        ($a['first_name'] ?? '')
                        .' '.
                        ($a['last_name'] ?? '')
                    ),

                    'reviewer_email'=>
                    (string)($a['email'] ?? ''),

                    'submission_title'=>
                    (
                        $a['title_en']
                        ??
                        $a['title_ar']
                        ??
                        ('Submission #'.$submissionId)
                    ),

                    'conference_title'=>
                    (
                        $a['conference_title_en']
                        ??
                        $a['conference_title_ar']
                        ??
                        ''
                    )

                ],

                $submissionId,

                (int)($a['reviewer_id'] ?? 0),

                (string)(
                    $a['preferred_lang']
                    ??
                    'en'
                )

            );

        }catch(\Throwable $e){

            error_log(
                'REVIEWER_UNASSIGN_EMAIL_FAIL='
                .$e->getMessage()
            );

        }

    }

    $_SESSION['toast']=[

        'type'=>'success',

        'msg'=>
        'Reviewer unassigned successfully'

    ];

    header(
    'Location: '.base_path('admin/reviewer-assignments')
    );

    exit;
}

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

    $id=(int)($_GET['id'] ?? 0);

    if(!$id){
        header('Location: '.base_path('admin/reviewer-assignments'));
        exit;
    }

    $db=Database::getInstance();

    $stmt=$db->prepare("
        SELECT
            ra.*,
            u.email,
            u.first_name,
            u.last_name,
            COALESCE(
                s.title_en,
                s.title_ar,
                CONCAT('Submission #',s.id)
            ) AS submission_title
        FROM review_assignments ra
        LEFT JOIN users u
            ON u.id=ra.reviewer_id
        LEFT JOIN submissions s
            ON s.id=ra.submission_id
        WHERE ra.id=?
        LIMIT 1
    ");

    $stmt->execute([$id]);

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

    if(!$a){
        header('Location: '.base_path('admin/reviewer-assignments'));
        exit;
    }

    if(
        strtolower((string)($a['status'] ?? ''))
        === 'completed'
    ){
        $_SESSION['toast']=[
            'type'=>'warning',
            'msg'=>'Review already completed'
        ];

        header('Location: '.base_path('admin/reviewer-assignments'));
        exit;
    }

    $subject=
        'Review Reminder - '.
        ($a['submission_title'] ?? '');

    $body=
        "Dear Reviewer\n\n".
        "This is a friendly reminder that your review assignment is still pending.\n\n".
        "Submission: ".
        ($a['submission_title'] ?? '').
        "\n\n".
        "Expected Review Period: 14 Days\n\n".
        "Please log in and complete your review.\n\n".
        "EasyChair Conference System";

    $db->prepare("
        INSERT INTO conference_mail_outbox
        (
            org_id,
            conference_id,
            submission_id,
            user_id,
            template_key,
            event_key,
            recipient_email,
            recipient_name,
            subject,
            body,
            status,
            created_by
        )
        VALUES
        (
            ?,?,?,?,?,?,?,?,?,?,
            'queued',
            ?
        )
    ")->execute([
        $a['org_id'] ?? null,
        $a['conference_id'],
        $a['submission_id'],
        $a['reviewer_id'],
        'review_reminder',
        'review_reminder',
        $a['email'],
        trim(
            ($a['first_name'] ?? '')
            .' '.
            ($a['last_name'] ?? '')
        ),
        $subject,
        $body,
        (int)($_SESSION['user_id'] ?? 0)
    ]);

    $_SESSION['toast']=[
        'type'=>'success',
        'msg'=>'Reminder queued successfully'
    ];

    header(
        'Location: '.base_path('admin/reviewer-assignments')
    );

    exit;
}

}
