<?php

namespace App\Controllers\Admin;

use App\Controllers\BaseController;
use App\Models\AscImportModel;
use App\Models\AscTeacherModel;
use App\Models\AscClassModel;
use App\Models\AscSubjectModel;
use App\Models\TeacherModel;
use App\Models\ClassroomModel;
use App\Models\SchoolSubjectModel;

class AscSync extends BaseController
{
    protected $importModel;
    protected $ascTeacherModel;
    protected $ascClassModel;
    protected $ascSubjectModel;
    protected $teacherModel;
    protected $classroomModel;
    protected $subjectModel;

    public function __construct()
    {
        $this->importModel     = new AscImportModel();
        $this->ascTeacherModel = new AscTeacherModel();
        $this->ascClassModel   = new AscClassModel();
        $this->ascSubjectModel = new AscSubjectModel();
        $this->teacherModel    = new TeacherModel();
        $this->classroomModel  = new ClassroomModel();
        $this->subjectModel    = new SchoolSubjectModel();
    }

    private function checkLogin()
    {
        if (!session()->get('logged_in')) {
            return redirect()->to('/login');
        }
        return null;
    }

    private function checkAdmin()
    {
        $role = session()->get('user_role');
        if (!in_array($role, ['superadmin', 'admin'])) {
            return redirect()->to('/dashboard')->with('error', 'Akses ditolak!');
        }
        return null;
    }

    // ══════════════════════════════════════════════════════════════════════
    // INDEX / HALAMAN SYNC
    // ══════════════════════════════════════════════════════════════════════

    public function index($importId = null)
    {
        if ($redirect = $this->checkLogin()) return $redirect;
        if ($redirect = $this->checkAdmin()) return $redirect;

        // Jika tidak ada importId, ambil yang aktif
        if (!$importId) {
            $active = $this->importModel->getActive();
            $importId = $active ? $active['id'] : null;
        }

        if (!$importId) {
            return redirect()->to('/asc-import')->with('error', 'Belum ada data import. Upload XML terlebih dahulu.');
        }

        $import = $this->importModel->find($importId);
        if (!$import) {
            return redirect()->to('/asc-import')->with('error', 'Import tidak ditemukan!');
        }

        // ── Data Guru ─────────────────────────────────────────────────────
        $ascTeachers = $this->ascTeacherModel->getByImport($importId);
        $existingTeachers = $this->getExistingTeachers();
        
        $teacherSync = [];
        foreach ($ascTeachers as $asc) {
            $matched = null;
            $status = 'not_sync';
            
            // Cek berdasarkan teacher_id (sudah sync sebelumnya)
            if ($asc['teacher_id']) {
                $matched = $this->teacherModel->find($asc['teacher_id']);
                if ($matched) {
                    $status = 'synced';
                }
            }
            
            // Jika belum, cari saran berdasarkan short_code
            if (!$matched && !empty($asc['asc_short_code'])) {
                foreach ($existingTeachers as $et) {
                    if ($et['short_code'] === $asc['asc_short_code']) {
                        $matched = $et;
                        // Status tetap 'not_sync' karena belum tersimpan di DB
                        break;
                    }
                }
            }
            
            $teacherSync[] = [
                'asc_id'         => $asc['id'],
                'asc_short_code' => $asc['asc_short_code'],
                'asc_name'       => $asc['asc_name'],
                'matched_id'     => $matched ? $matched['id'] : null,
                'matched_name'   => $matched ? $matched['name'] : null,
                'matched_short'  => $matched ? $matched['short_code'] : null,
                'status'         => $status,
            ];
        }
        
        $db = \Config\Database::connect();
        $yearRow = $db->table('academic_years')
                      ->where('name', $import['academic_year'])
                      ->where('deleted_at', null)
                      ->get()->getRowArray();
        $academicYearId = $yearRow ? $yearRow['id'] : null;

        // ── Data Kelas ────────────────────────────────────────────────────
        $ascClasses = $this->ascClassModel->getByImport($importId);
        $existingClasses = $this->getExistingClasses($academicYearId);
        
        $classSync = [];
        foreach ($ascClasses as $asc) {
            $matched = null;
            $status = 'not_sync';
            
            // Cek berdasarkan classroom_id (sudah sync sebelumnya)
            if ($asc['classroom_id']) {
                $matched = $this->classroomModel->find($asc['classroom_id']);
                if ($matched) {
                    $status = 'synced';
                }
            }
            
            // Jika belum, cari saran berdasarkan kesamaan nama
            if (!$matched) {
                foreach ($existingClasses as $ec) {
                    if ($ec['name'] === $asc['asc_name']) {
                        $matched = $ec;
                        // Status tetap 'not_sync' karena belum tersimpan di DB
                        break;
                    }
                }
            }
            
            $classSync[] = [
                'asc_id'       => $asc['id'],
                'asc_name'     => $asc['asc_name'],
                'matched_id'   => $matched ? $matched['id'] : null,
                'matched_name' => $matched ? $matched['name'] : null,
                'status'       => $status,
            ];
        }
        
        // ── Data Mata Pelajaran ──────────────────────────────────────────
        $ascSubjects = $this->ascSubjectModel->getByImport($importId);
        $existingSubjects = $this->getExistingSubjects();
        
        $subjectSync = [];
        foreach ($ascSubjects as $asc) {
            $matched = null;
            $status = 'not_sync';
            
            // Cek berdasarkan school_subject_id (sudah sync sebelumnya)
            if ($asc['school_subject_id']) {
                $matched = $this->subjectModel->find($asc['school_subject_id']);
                if ($matched) {
                    $status = 'synced';
                }
            }
            
            // Jika belum, cari saran berdasarkan kode atau nama
            if (!$matched) {
                foreach ($existingSubjects as $es) {
                    if ($es['code'] === $asc['short_code'] || $es['name'] === $asc['name']) {
                        $matched = $es;
                        // Status tetap 'not_sync' karena belum tersimpan di DB
                        break;
                    }
                }
            }
            
            $subjectSync[] = [
                'asc_id'        => $asc['id'],
                'asc_code'      => $asc['short_code'],
                'asc_name'      => $asc['name'],
                'matched_id'    => $matched ? $matched['id'] : null,
                'matched_name'  => $matched ? $matched['name'] : null,
                'matched_code'  => $matched ? $matched['code'] : null,
                'status'        => $status,
            ];
        }
        
        $data = [
            'title'             => 'Sync Data - ' . $import['name'],
            'import'            => $import,
            'imports'           => $this->importModel->getAll(),
            'import_id'         => $importId,
            'teacher_sync'      => $teacherSync,
            'class_sync'        => $classSync,
            'subject_sync'      => $subjectSync,
            'existing_teachers' => $existingTeachers,
            'existing_classes'  => $existingClasses,
            'existing_subjects' => $existingSubjects,
        ];
        
        return view('asc/sync/index', $data);
    }
    
    // ══════════════════════════════════════════════════════════════════════
    // GET EXISTING DATA (untuk dropdown)
    // ══════════════════════════════════════════════════════════════════════
    
    private function getExistingTeachers()
    {
        return $this->teacherModel->select('id, name, short_code, nip')
                    ->where('deleted_at', null)
                    ->orderBy('name', 'ASC')
                    ->findAll();
    }
    
    private function getExistingClasses($academicYearId = null)
    {
        $builder = $this->classroomModel
                    ->select('classrooms.id, classrooms.name, grades.name as grade_name')
                    ->join('grades', 'grades.id = classrooms.grade_id', 'left')
                    ->where('classrooms.deleted_at', null);

        if ($academicYearId) {
            $builder->where('classrooms.academic_year_id', $academicYearId);
        }

        return $builder->orderBy('classrooms.name', 'ASC')
                    ->findAll();
    }
    
    private function getExistingSubjects()
    {
        return $this->subjectModel->select('id, name, code')
                    ->where('deleted_at', null)
                    ->orderBy('name', 'ASC')
                    ->findAll();
    }
    
    // ══════════════════════════════════════════════════════════════════════
    // SYNC GURU
    // ══════════════════════════════════════════════════════════════════════
    
    public function syncTeacher()
    {
        if ($redirect = $this->checkLogin()) return $redirect;
        if ($redirect = $this->checkAdmin()) return $redirect;
        
        $ascId = $this->request->getPost('asc_id');
        $teacherId = $this->request->getPost('teacher_id');
        
        if (!$ascId) {
            return $this->response->setJSON(['success' => false, 'message' => 'Data tidak valid!']);
        }
        
        // Update asc_teachers
        $ascTeacher = $this->ascTeacherModel->find($ascId);
        if (!$ascTeacher) {
            return $this->response->setJSON(['success' => false, 'message' => 'Data aSc tidak ditemukan!']);
        }
        
        $this->ascTeacherModel->update($ascId, ['teacher_id' => $teacherId ?: null]);
        
        // Salin short_code yang benar dari database ke staging aSc
        if ($teacherId) {
            $existingTeacher = $this->teacherModel->find($teacherId);
            if ($existingTeacher && !empty($existingTeacher['short_code'])) {
                $this->ascTeacherModel->update($ascId, ['short_code' => $existingTeacher['short_code']]);
            }
        }
        
        return $this->response->setJSON([
            'success' => true,
            'message' => 'Sync guru berhasil!',
            'csrf_token' => csrf_hash()
        ]);
    }
    
    public function syncTeacherBulk()
    {
        if ($redirect = $this->checkLogin()) return $redirect;
        if ($redirect = $this->checkAdmin()) return $redirect;
        
        $raw = $this->request->getBody();
        $data = json_decode($raw, true);
        $mappings = $data['mappings'] ?? [];
        
        if (empty($mappings)) {
            $mappings = $this->request->getPost('mappings');
        }
        
        if (!$mappings || !is_array($mappings)) {
            return $this->response->setJSON(['success' => false, 'message' => 'Data tidak valid!']);
        }
        
        $count = 0;
        foreach ($mappings as $mapping) {
            if (!empty($mapping['asc_id']) && !empty($mapping['teacher_id'])) {
                $this->ascTeacherModel->update($mapping['asc_id'], ['teacher_id' => $mapping['teacher_id']]);
                
                // Salin short_code yang benar dari database ke staging aSc
                $existingTeacher = $this->teacherModel->find($mapping['teacher_id']);
                if ($existingTeacher && !empty($existingTeacher['short_code'])) {
                    $this->ascTeacherModel->update($mapping['asc_id'], ['short_code' => $existingTeacher['short_code']]);
                }
                
                $count++;
            }
        }
        
        return $this->response->setJSON([
            'success' => true,
            'message' => "{$count} guru berhasil disync!",
            'csrf_token' => csrf_hash()
        ]);
    }

    private function cleanTeacherName($name)
    {
        $name = strtolower($name);
        $titles = [
            'drs.', 'dra.', 'h.', 'hj.', 's.pd.i.', 's.pd.i', 's.pd', 's. pd.', 's. pd. i.', 's. pd', 's.ag.', 's. ag.',
            's.si.', 's. si.', 'm.pd.', 'm. pd.', 'm.pd.i', 'm. pd. i', 'm.or.', 'm. or.', 's.s.', 's. s.',
            ',', '.', '  '
        ];
        $name = str_replace($titles, ' ', $name);
        $name = preg_replace('/\s+/', ' ', $name);
        return trim($name);
    }
    
    public function autoMatchTeacher()
    {
        if ($redirect = $this->checkLogin()) return $redirect;
        if ($redirect = $this->checkAdmin()) return $redirect;
        
        $importId = $this->request->getPost('import_id');
        if (!$importId) {
            return $this->response->setJSON(['success' => false, 'message' => 'Import ID diperlukan!']);
        }
        
        $ascTeachers = $this->ascTeacherModel->getByImport($importId);
        $existingTeachers = $this->getExistingTeachers();
        
        $matched = 0;
        $results = []; // untuk detail hasil match
        
        foreach ($ascTeachers as $asc) {
            // Cek sudah punya match?
            if ($asc['teacher_id']) continue;
            
            $bestMatch = null;
            $bestPercent = 0;
            $matchType = '';
            
            $cleanAsc = $this->cleanTeacherName($asc['asc_name'] ?? $asc['name']);

            // 1. Coba cari nama yang sangat mirip (>= 85%) - independent of code
            foreach ($existingTeachers as $et) {
                $cleanEt = $this->cleanTeacherName($et['name']);
                similar_text($cleanAsc, $cleanEt, $percent);
                if ($percent > $bestPercent && $percent >= 85) {
                    $bestPercent = $percent;
                    $bestMatch = $et;
                    $matchType = 'STRONG_NAME';
                }
            }

            // 2. Jika tidak ada yang sangat mirip, coba match berdasarkan short_code dengan kemiripan nama >= 80%
            if (!$bestMatch && !empty($asc['asc_short_code'] ?? $asc['short_code'])) {
                foreach ($existingTeachers as $et) {
                    if (!empty($et['short_code']) && strtolower($et['short_code']) === strtolower($asc['asc_short_code'] ?? $asc['short_code'])) {
                        $cleanEt = $this->cleanTeacherName($et['name']);
                        similar_text($cleanAsc, $cleanEt, $namePercent);
                        if ($namePercent >= 80) {
                            $bestMatch = $et;
                            $bestPercent = $namePercent;
                            $matchType = 'CODE_WITH_NAME';
                            break;
                        }
                    }
                }
            }

            // 3. Fallback ke kemiripan nama sedang (>= 80%)
            if (!$bestMatch) {
                foreach ($existingTeachers as $et) {
                    $cleanEt = $this->cleanTeacherName($et['name']);
                    similar_text($cleanAsc, $cleanEt, $percent);
                    if ($percent > $bestPercent && $percent >= 80) {
                        $bestPercent = $percent;
                        $bestMatch = $et;
                        $matchType = 'WEAK_NAME';
                    }
                }
            }
            
            if ($bestMatch) {
                $this->ascTeacherModel->update($asc['id'], ['teacher_id' => $bestMatch['id']]);
                
                // Salin short_code yang benar dari database ke staging aSc
                if (!empty($bestMatch['short_code'])) {
                    $this->ascTeacherModel->update($asc['id'], ['short_code' => $bestMatch['short_code']]);
                }
                
                $matched++;
                $results[] = "{$asc['asc_name']} → {$bestMatch['name']} (" . round($bestPercent, 1) . "%)";
            }
        }
        
        $message = "Auto-match selesai! {$matched} guru berhasil disync.";
        if (!empty($results) && $matched <= 10) {
            $message .= "\n\nDetail:\n" . implode("\n", $results);
        }
        
        return $this->response->setJSON([
            'success' => true,
            'message' => $message,
            'csrf_token' => csrf_hash()
        ]);
    }
    
    // ══════════════════════════════════════════════════════════════════════
    // SYNC KELAS
    // ══════════════════════════════════════════════════════════════════════
    
    public function syncClass()
    {
        if ($redirect = $this->checkLogin()) return $redirect;
        if ($redirect = $this->checkAdmin()) return $redirect;
        
        $ascId = $this->request->getPost('asc_id');
        $classroomId = $this->request->getPost('classroom_id');
        
        if (!$ascId) {
            return $this->response->setJSON(['success' => false, 'message' => 'Data tidak valid!']);
        }
        
        $this->ascClassModel->update($ascId, ['classroom_id' => $classroomId ?: null]);
        
        return $this->response->setJSON([
            'success' => true,
            'message' => 'Sync kelas berhasil!',
            'csrf_token' => csrf_hash()
        ]);
    }
    
    public function syncClassBulk()
    {
        if ($redirect = $this->checkLogin()) return $redirect;
        if ($redirect = $this->checkAdmin()) return $redirect;
        
        $raw = $this->request->getBody();
        $data = json_decode($raw, true);
        $mappings = $data['mappings'] ?? [];
        
        if (empty($mappings)) {
            $mappings = $this->request->getPost('mappings');
        }
        
        if (!$mappings || !is_array($mappings)) {
            return $this->response->setJSON(['success' => false, 'message' => 'Data tidak valid!']);
        }
        
        $count = 0;
        foreach ($mappings as $mapping) {
            if (!empty($mapping['asc_id']) && !empty($mapping['classroom_id'])) {
                $this->ascClassModel->update($mapping['asc_id'], ['classroom_id' => $mapping['classroom_id']]);
                $count++;
            }
        }
        
        return $this->response->setJSON([
            'success' => true,
            'message' => "Bulk sync kelas berhasil! {$count} kelas disinkronkan.",
            'csrf_token' => csrf_hash()
        ]);
    }
    
    public function autoMatchClass()
    {
        if ($redirect = $this->checkLogin()) return $redirect;
        if ($redirect = $this->checkAdmin()) return $redirect;
        
        $importId = $this->request->getPost('import_id');
        if (!$importId) {
            return $this->response->setJSON(['success' => false, 'message' => 'Import ID diperlukan!']);
        }
        
        $import = $this->importModel->find($importId);
        $academicYearId = null;
        if ($import) {
            $db = \Config\Database::connect();
            $yearRow = $db->table('academic_years')
                          ->where('name', $import['academic_year'])
                          ->where('deleted_at', null)
                          ->get()->getRowArray();
            $academicYearId = $yearRow ? $yearRow['id'] : null;
        }

        $ascClasses = $this->ascClassModel->getByImport($importId);
        $existingClasses = $this->getExistingClasses($academicYearId);
        
        $matched = 0;
        foreach ($ascClasses as $asc) {
            if ($asc['classroom_id']) continue;
            
            $found = null;
            foreach ($existingClasses as $ec) {
                if ($ec['name'] === $asc['name']) {
                    $found = $ec;
                    break;
                }
            }
            
            if ($found) {
                $this->ascClassModel->update($asc['id'], ['classroom_id' => $found['id']]);
                $matched++;
            }
        }
        
        return $this->response->setJSON([
            'success' => true,
            'message' => "Auto-match selesai! {$matched} kelas berhasil disync.",
            'csrf_token' => csrf_hash()
        ]);
    }
    
    // ══════════════════════════════════════════════════════════════════════
    // SYNC MATA PELAJARAN
    // ══════════════════════════════════════════════════════════════════════
    
    public function syncSubject()
    {
        if ($redirect = $this->checkLogin()) return $redirect;
        if ($redirect = $this->checkAdmin()) return $redirect;
        
        $ascId = $this->request->getPost('asc_id');
        $subjectId = $this->request->getPost('subject_id');
        
        if (!$ascId) {
            return $this->response->setJSON(['success' => false, 'message' => 'Data tidak valid!']);
        }
        
        $this->ascSubjectModel->update($ascId, ['school_subject_id' => $subjectId ?: null]);
        
        return $this->response->setJSON([
            'success' => true,
            'message' => 'Sync mata pelajaran berhasil!',
            'csrf_token' => csrf_hash()
        ]);
    }
    
    public function syncSubjectBulk()
    {
        if ($redirect = $this->checkLogin()) return $redirect;
        if ($redirect = $this->checkAdmin()) return $redirect;
        
        $raw = $this->request->getBody();
        $data = json_decode($raw, true);
        $mappings = $data['mappings'] ?? [];
        
        if (empty($mappings)) {
            $mappings = $this->request->getPost('mappings');
        }
        
        if (!$mappings || !is_array($mappings)) {
            return $this->response->setJSON(['success' => false, 'message' => 'Data tidak valid!']);
        }
        
        $count = 0;
        foreach ($mappings as $mapping) {
            if (!empty($mapping['asc_id']) && !empty($mapping['subject_id'])) {
                $this->ascSubjectModel->update($mapping['asc_id'], ['school_subject_id' => $mapping['subject_id']]);
                $count++;
            }
        }
        
        return $this->response->setJSON([
            'success' => true,
            'message' => "Bulk sync mata pelajaran berhasil! {$count} mata pelajaran disinkronkan.",
            'csrf_token' => csrf_hash()
        ]);
    }
    
    public function autoMatchSubject()
    {
        if ($redirect = $this->checkLogin()) return $redirect;
        if ($redirect = $this->checkAdmin()) return $redirect;
        
        $importId = $this->request->getPost('import_id');
        if (!$importId) {
            return $this->response->setJSON(['success' => false, 'message' => 'Import ID diperlukan!']);
        }
        
        $ascSubjects = $this->ascSubjectModel->getByImport($importId);
        $existingSubjects = $this->getExistingSubjects();
        
        $matched = 0;
        foreach ($ascSubjects as $asc) {
            if ($asc['school_subject_id']) continue;
            
            $found = null;
            foreach ($existingSubjects as $es) {
                if ($es['code'] === $asc['short_code'] || $es['name'] === $asc['name']) {
                    $found = $es;
                    break;
                }
            }
            
            if ($found) {
                $this->ascSubjectModel->update($asc['id'], ['school_subject_id' => $found['id']]);
                $matched++;
            }
        }
        
        return $this->response->setJSON([
            'success' => true,
            'message' => "Auto-match selesai! {$matched} mata pelajaran berhasil disync.",
            'csrf_token' => csrf_hash()
        ]);
    }
    
    // ══════════════════════════════════════════════════════════════════════
    // RESET SYNC
    // ══════════════════════════════════════════════════════════════════════
    
    public function reset($importId, $type)
    {
        if ($redirect = $this->checkLogin()) return $redirect;
        if ($redirect = $this->checkAdmin()) return $redirect;
        
        switch ($type) {
            case 'teacher':
                $this->ascTeacherModel->where('import_id', $importId)->set(['teacher_id' => null])->update();
                break;
            case 'class':
                $this->ascClassModel->where('import_id', $importId)->set(['classroom_id' => null])->update();
                break;
            case 'subject':
                $this->ascSubjectModel->where('import_id', $importId)->set(['school_subject_id' => null])->update();
                break;
            default:
                return redirect()->back()->with('error', 'Tipe tidak valid!');
        }
        
        return redirect()->back()->with('success', "Reset sync {$type} berhasil!");
    }
}