<?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 PDO;

final class AdminScheduleTenantController extends Controller
{
    private function confOrFail($db, int $orgId, int $confId): array {
        $st=$db->prepare("SELECT * FROM conferences WHERE id=:id AND org_id=:o LIMIT 1");
        $st->execute([':id'=>$confId, ':o'=>$orgId]);
        $row=$st->fetch(PDO::FETCH_ASSOC);
        if(!$row){ http_response_code(404); echo "Conference not found"; exit; }
        return $row;
    }

    private function tableExists(PDO $db, string $t): bool {
        $st=$db->prepare("SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=:t");
        $st->execute([':t'=>$t]);
        return (int)$st->fetchColumn() > 0;
    }

    private function colExists(PDO $db, string $t, string $c): bool {
        $st=$db->prepare("SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=:t AND COLUMN_NAME=:c");
        $st->execute([':t'=>$t, ':c'=>$c]);
        return (int)$st->fetchColumn() > 0;
    }

    private function pickDateCol(PDO $db, string $t): ?string {
        foreach(['day_date','program_date','date','session_date'] as $c){
            if($this->colExists($db,$t,$c)) return $c;
        }
        return null;
    }

    private function ensureProgramDay(PDO $db, int $orgId, int $confId, string $date): int
    {
        $t='conference_program_days';
        if(!$this->tableExists($db,$t)){
            // FK exists, so table SHOULD exist; if not, hard fail clearly.
            throw new \RuntimeException("conference_program_days missing");
        }

        $dateCol = $this->pickDateCol($db,$t);
        if(!$dateCol){
            throw new \RuntimeException("conference_program_days has no date column");
        }

        // try find existing
        $sql="SELECT id FROM `$t` WHERE conference_id=:c AND `$dateCol`=:d LIMIT 1";
        $st=$db->prepare($sql);
        $st->execute([':c'=>$confId, ':d'=>$date]);
        $id=(int)$st->fetchColumn();
        if($id>0) return $id;

        // create minimal row safely (only set columns we know are safe)
        $cols=['conference_id'];
        $vals=[':conference_id'];
        $bind=[':conference_id'=>$confId];

        // org_id if exists
        if($this->colExists($db,$t,'org_id')){
            $cols[]='org_id'; $vals[]=':org_id'; $bind[':org_id']=$orgId;
        }

        // date col
        $cols[]=$dateCol; $vals[]=':d'; $bind[':d']=$date;

        // titles (optional)
        if($this->colExists($db,$t,'title_en')){
            $cols[]='title_en'; $vals[]=':te'; $bind[':te']="Program Day $date";
        }
        if($this->colExists($db,$t,'title_ar')){
            $cols[]='title_ar'; $vals[]=':ta'; $bind[':ta']="يوم البرنامج $date";
        }

        // sort_order optional
        if($this->colExists($db,$t,'sort_order')){
            $cols[]='sort_order'; $vals[]='0';
        }

        // is_active optional
        if($this->colExists($db,$t,'is_active')){
            $cols[]='is_active'; $vals[]='1';
        }

        $ins="INSERT INTO `$t` (".implode(',',$cols).") VALUES (".implode(',',$vals).")";
        $st=$db->prepare($ins);
        $st->execute($bind);

        return (int)$db->lastInsertId();
    }

    private function baseData(): array
    {
        require_admin_or_chair_tenant();
        require_org_context();

        $db=Database::getInstance();
        $orgId=(int)current_org_id();

        $st=$db->prepare("SELECT id,title_en,title_ar,start_date,end_date FROM conferences WHERE org_id=:o ORDER BY id DESC");
        $st->execute([':o'=>$orgId]);
        $confs=$st->fetchAll(PDO::FETCH_ASSOC)?:[];

        $confId=(int)($_GET['conference_id'] ?? ($confs[0]['id'] ?? 0));
        $conf = $confId ? $this->confOrFail($db,$orgId,$confId) : null;

        $sessions=[];
        if($confId>0){
            $st=$db->prepare("
                SELECT s.*
                FROM conference_sessions s
                JOIN conferences c ON c.id=s.conference_id
                WHERE s.conference_id=:c AND c.org_id=:o
                ORDER BY COALESCE(s.session_date, c.start_date) ASC, s.start_time ASC, s.id ASC
            ");
            $st->execute([':c'=>$confId, ':o'=>$orgId]);
            $sessions=$st->fetchAll(PDO::FETCH_ASSOC)?:[];
        }

        // program days list (for dropdown)
        $programDays=[];
        if($confId>0 && $this->tableExists($db,'conference_program_days')){
            $dateCol = $this->pickDateCol($db,'conference_program_days');
            if($dateCol){
                $st=$db->prepare("SELECT id, `$dateCol` AS d FROM conference_program_days WHERE conference_id=:c ORDER BY `$dateCol` ASC, id ASC");
                $st->execute([':c'=>$confId]);
                $programDays=$st->fetchAll(PDO::FETCH_ASSOC)?:[];
            }
        }

        return compact('db','orgId','confs','confId','conf','sessions','programDays');
    }

    // /admin/schedule
    public function schedule(): void
    {
        $data=$this->baseData();
        $timeline=[];
        foreach($data['sessions'] as $s){
            $d=(string)($s['session_date'] ?? '');
            if($d==='') $d='(no date)';
            $timeline[$d]=$timeline[$d]??[];
            $timeline[$d][]=$s;
        }
        $data['timeline']=$timeline;
        $this->view('admin/schedule/schedule', $data);
    }

    // /admin/sessions
    public function sessions(): void
    {
        $data=$this->baseData();
        $this->view('admin/schedule/sessions', $data);
    }

    // called by /action/sessions
    public function save(): void
    {
        require_admin_or_chair_tenant();
        require_org_context();

        $db=Database::getInstance();
        $orgId=(int)current_org_id();

        $id=(int)($_POST['id'] ?? 0);
        $confId=(int)($_POST['conference_id'] ?? 0);
        $conf=$this->confOrFail($db,$orgId,$confId);

        $sessionDate = trim((string)($_POST['session_date'] ?? ''));
        if($sessionDate===''){
            // fallback to conference start_date if available
            $sessionDate = (string)($conf['start_date'] ?? '');
        }
        if($sessionDate===''){
            // last resort: today
            $sessionDate = date('Y-m-d');
        }

        $programDayId=(int)($_POST['program_day_id'] ?? 0);
        if($programDayId<=0){
            $programDayId = $this->ensureProgramDay($db,$orgId,$confId,$sessionDate);
        }

        $data=[
          'conference_id'=>$confId,
          'org_id'=>$orgId,
          'program_day_id'=>$programDayId,
          'session_date'=>$sessionDate ?: null,
          'start_time'=>trim((string)($_POST['start_time'] ?? '')),
          'end_time'=>trim((string)($_POST['end_time'] ?? '')),
          'session_type'=>trim((string)($_POST['session_type'] ?? 'paper_session')),
          'title_en'=>trim((string)($_POST['title_en'] ?? '')),
          'title_ar'=>trim((string)($_POST['title_ar'] ?? '')),
          'room_name'=>trim((string)($_POST['room_name'] ?? '')) ?: null,
          'chair_name_en'=>trim((string)($_POST['chair_name_en'] ?? '')) ?: null,
          'chair_name_ar'=>trim((string)($_POST['chair_name_ar'] ?? '')) ?: null,
          'sort_order'=>(int)($_POST['sort_order'] ?? 0),
          'is_active'=>((int)($_POST['is_active'] ?? 1)) ? 1 : 0,
        ];

        if($data['start_time']==='' || $data['end_time']==='' || $data['title_en']===''){
            if(function_exists('flash_set')) flash_set('danger','Please fill Title (EN), Start, End');
            header('Location: '.base_path('admin/sessions?conference_id='.$confId)); exit;
        }

        if($id>0){
            $st=$db->prepare("
              SELECT s.id FROM conference_sessions s
              JOIN conferences c ON c.id=s.conference_id
              WHERE s.id=:id AND c.org_id=:o
              LIMIT 1
            ");
            $st->execute([':id'=>$id,':o'=>$orgId]);
            if(!(int)$st->fetchColumn()){ http_response_code(404); echo "Not found"; exit; }

            $db->prepare("
              UPDATE conference_sessions SET
                conference_id=:conference_id,
                org_id=:org_id,
                program_day_id=:program_day_id,
                session_date=:session_date,
                start_time=:start_time,
                end_time=:end_time,
                session_type=:session_type,
                title_en=:title_en,
                title_ar=:title_ar,
                room_name=:room_name,
                chair_name_en=:chair_name_en,
                chair_name_ar=:chair_name_ar,
                sort_order=:sort_order,
                is_active=:is_active
              WHERE id=:id
            ")->execute($data + [':id'=>$id]);
        } else {
            $db->prepare("
              INSERT INTO conference_sessions(
                conference_id, org_id, program_day_id, session_date,
                start_time, end_time, session_type,
                title_en, title_ar, room_name, chair_name_en, chair_name_ar,
                sort_order, is_active
              ) VALUES (
                :conference_id, :org_id, :program_day_id, :session_date,
                :start_time, :end_time, :session_type,
                :title_en, :title_ar, :room_name, :chair_name_en, :chair_name_ar,
                :sort_order, :is_active
              )
            ")->execute($data);
        }

        if(function_exists('flash_set')) flash_set('success','Saved');
        header('Location: '.base_path('admin/sessions?conference_id='.$confId)); exit;
    }

    public function delete(): void
    {
        require_admin_or_chair_tenant();
        require_org_context();

        $db=Database::getInstance();
        $orgId=(int)current_org_id();
        $id=(int)($_GET['id'] ?? 0);

        $st=$db->prepare("
          SELECT s.id, s.conference_id FROM conference_sessions s
          JOIN conferences c ON c.id=s.conference_id
          WHERE s.id=:id AND c.org_id=:o
          LIMIT 1
        ");
        $st->execute([':id'=>$id,':o'=>$orgId]);
        $row=$st->fetch(PDO::FETCH_ASSOC);
        if(!$row){ http_response_code(404); echo "Not found"; exit; }

        $db->prepare("DELETE FROM conference_sessions WHERE id=:id")->execute([':id'=>$id]);

        if(function_exists('flash_set')) flash_set('success','Deleted');
        header('Location: '.base_path('admin/sessions?conference_id='.(int)$row['conference_id'])); exit;
    }
}
