<?php

namespace App\Http\Controllers;

use App\Enums\JenisIzin;
use App\Enums\StatusPengajuan;
use App\Enums\StatusPresensi;
use App\Enums\StatusSurat;
use App\Enums\StatusValidasi;
use App\Events\SuratIzinUpdated;
use App\Models\SuratIzin;
use App\Models\ApprovalSurat;
use App\Models\TandaTangan;
use App\Models\Presensi;
use App\Services\NotifikasiService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

class SuratIzinController extends Controller
{
    public function index(Request $request)
    {
        $user = Auth::user();
        $isGlobalAdmin = $user->isGlobalAdmin();

        $query = SuratIzin::with(['user', 'pengajuanIzin.jenisIzin', 'approvals.approver']);

        if (!$isGlobalAdmin) {
            if (!$user->roles->contains('nama_role', 'manajer')) {
                $query->where('status_surat', '!=', StatusSurat::MENUNGGU_MANAJER);
            }
            $query->whereHas('user', function ($q) use ($user) {
                $q->where('id_kantor', $user->id_kantor);
            });
        }

        if ($request->filled('status')) {
            $query->where('status_surat', $request->status);
        }

        if ($request->filled('search')) {
            $query->whereHas('user', function ($q) use ($request) {
                $q->where('nama_lengkap', 'like', '%' . $request->search . '%');
            });
        }

        $suratList = $query->orderBy('created_at', 'desc')->paginate(15);

        return view('surat-izin.index', compact('suratList'));
    }

    public function show($id)
    {
        $surat = SuratIzin::with([
            'user.jabatan',
            'user.divisi',
            'pengajuanIzin.jenisIzin',
            'tandaTanganPengaju',
            'approvals.approver.jabatan',
            'approvals.tandaTanganApprover',
        ])->findOrFail($id);

        $user = Auth::user();
        $isGlobalAdmin = $user->isGlobalAdmin();

        // Security Check: Office Isolation
        if (!$isGlobalAdmin && $surat->user->id_kantor != $user->id_kantor) {
            abort(403, 'Anda tidak diizinkan mengakses data dari kantor lain.');
        }

        $canApprove = false;
        $tahapApproval = null;

        // Cegah user yang sama menandatangani di dua tahap berbeda
        $sudahApprove = $surat->approvals->contains('id_approver', $user->id);

        if (!$sudahApprove && $surat->status_surat === StatusSurat::MENUNGGU_MANAJER && ($user->roles->contains('nama_role', 'manajer') || $isGlobalAdmin)) {
            $canApprove = true;
            $tahapApproval = 1;
        } elseif (!$sudahApprove && $surat->status_surat === StatusSurat::MENUNGGU_HRD && ($user->roles->contains('nama_role', 'hrd') || $isGlobalAdmin)) {
            $canApprove = true;
            $tahapApproval = 2;
        }

        $ttdApprover = TandaTangan::where('id_user', $user->id)->active()->first();

        return view('surat-izin.show', compact('surat', 'canApprove', 'tahapApproval', 'ttdApprover'));
    }

    public function approve(Request $request, $id)
    {
        try {
            $surat = SuratIzin::with('user')->findOrFail($id);
            $user = Auth::user();
            $isGlobalAdmin = $user->isGlobalAdmin();

            // Security Check
            if (!$isGlobalAdmin && $surat->user->id_kantor != $user->id_kantor) {
                return redirect()->back()->with('error', 'Anda tidak diizinkan menyetujui surat dari karyawan kantor lain.');
            }

            if (in_array($surat->status_surat, [StatusSurat::DISETUJUI, StatusSurat::DITOLAK])) {
                return redirect()->back()->with('error', 'Surat ini sudah diproses sebelumnya.');
            }

            $tahap = null;

            // Cegah approver yang sama menandatangani di dua posisi berbeda
            $sudahApprove = ApprovalSurat::where('id_surat', $surat->id_surat)
                ->where('id_approver', $user->id)
                ->exists();

            if ($sudahApprove) {
                return redirect()->back()->with('error', 'Anda sudah menyetujui surat ini sebelumnya dan tidak dapat menandatangani di posisi lain.');
            }

            if ($surat->status_surat === StatusSurat::MENUNGGU_MANAJER && ($user->roles->contains('nama_role', 'manajer') || $isGlobalAdmin)) {
                $tahap = 1;
            } elseif ($surat->status_surat === StatusSurat::MENUNGGU_HRD && ($user->roles->contains('nama_role', 'hrd') || $isGlobalAdmin)) {
                $tahap = 2;
            }

            if (!$tahap) {
                return redirect()->back()->with('error', 'Anda tidak memiliki akses untuk menyetujui surat ini.');
            }

            $ttd = TandaTangan::where('id_user', $user->id)->active()->first();
            if (!$ttd) {
                return redirect()->back()->with('error', 'Anda belum memiliki tanda tangan digital.');
            }

            DB::beginTransaction();

            ApprovalSurat::create([
                'id_surat' => $surat->id_surat,
                'id_approver' => $user->id,
                'id_ttd_approver' => $ttd->id_tanda_tangan,
                'tahap' => $tahap,
                'status' => 'disetujui',
                'catatan' => $request->catatan,
            ]);

            if ($tahap === 1) {
                $surat->update(['status_surat' => StatusSurat::MENUNGGU_HRD]);
            } elseif ($tahap === 2) {
                $surat->update(['status_surat' => StatusSurat::DISETUJUI]);
                $this->prosesPersetujuanFinal($surat);
            }

            DB::commit();

            if ($tahap === 1) {
                $statusLabel = 'Menunggu HRD';
                app(NotifikasiService::class)->kirim(
                    $surat->id_user,
                    'izin_proses',
                    'Surat Izin Diproses',
                    'Surat izin Anda telah disetujui Manajer dan sedang menunggu persetujuan HRD.',
                    ['id_surat' => $surat->id_surat]
                );
            } else {
                $statusLabel = 'Disetujui';
                app(NotifikasiService::class)->kirim(
                    $surat->id_user,
                    'izin_disetujui',
                    'Surat Izin Disetujui ✅',
                    'Surat izin Anda telah disetujui sepenuhnya.',
                    ['id_surat' => $surat->id_surat]
                );
            }

            broadcast(new SuratIzinUpdated(
                $surat->id_user,
                $surat->id_surat,
                $surat->status_surat,
                $tahap,
                'Surat izin ' . ($tahap === 1 ? 'disetujui Manajer' : 'disetujui sepenuhnya') . '.'
            ));

            return redirect()->back()->with('success', "Surat berhasil disetujui. Status: {$statusLabel}");

        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->back()->with('error', 'Gagal: ' . $e->getMessage());
        }
    }

    public function reject(Request $request, $id)
    {
        try {
            $surat = SuratIzin::with(['user', 'pengajuanIzin'])->findOrFail($id);
            $user = Auth::user();
            $isGlobalAdmin = $user->isGlobalAdmin();

            // Security Check
            if (!$isGlobalAdmin && $surat->user->id_kantor != $user->id_kantor) {
                return redirect()->back()->with('error', 'Anda tidak diizinkan menolak surat dari karyawan kantor lain.');
            }

            if (in_array($surat->status_surat, [StatusSurat::DISETUJUI, StatusSurat::DITOLAK])) {
                return redirect()->back()->with('error', 'Surat ini sudah diproses sebelumnya.');
            }

            $tahap = null;

            // Cegah approver yang sama menandatangani di dua posisi berbeda
            $sudahApprove = ApprovalSurat::where('id_surat', $surat->id_surat)
                ->where('id_approver', $user->id)
                ->exists();

            if ($sudahApprove) {
                return redirect()->back()->with('error', 'Anda sudah menyetujui surat ini sebelumnya dan tidak dapat menolak di posisi lain.');
            }

            if ($surat->status_surat === StatusSurat::MENUNGGU_MANAJER && ($user->roles->contains('nama_role', 'manajer') || $isGlobalAdmin)) {
                $tahap = 1;
            } elseif ($surat->status_surat === StatusSurat::MENUNGGU_HRD && ($user->roles->contains('nama_role', 'hrd') || $isGlobalAdmin)) {
                $tahap = 2;
            }

            if (!$tahap) {
                return redirect()->back()->with('error', 'Anda tidak memiliki akses.');
            }

            DB::beginTransaction();

            ApprovalSurat::create([
                'id_surat' => $surat->id_surat,
                'id_approver' => $user->id,
                'id_ttd_approver' => null,
                'tahap' => $tahap,
                'status' => 'ditolak',
                'catatan' => $request->catatan,
            ]);

            $surat->update(['status_surat' => StatusSurat::DITOLAK]);

            if ($surat->pengajuanIzin) {
                $surat->pengajuanIzin->update(['id_status' => StatusPengajuan::DITOLAK]);
            }

            DB::commit();

            app(NotifikasiService::class)->kirim(
                $surat->id_user,
                'izin_ditolak',
                'Surat Izin Ditolak ❌',
                'Surat izin Anda ditolak. Catatan: ' . ($request->catatan ?? '-'),
                ['id_surat' => $surat->id_surat]
            );

            broadcast(new SuratIzinUpdated(
                $surat->id_user,
                $surat->id_surat,
                StatusSurat::DITOLAK,
                $tahap,
                'Surat izin ditolak.'
            ));

            return redirect()->back()->with('success', 'Surat izin berhasil ditolak.');

        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->back()->with('error', 'Gagal: ' . $e->getMessage());
        }
    }

    private function prosesPersetujuanFinal(SuratIzin $surat)
    {
        $izin = $surat->pengajuanIzin;
        if (!$izin)
            return;

        $izin->load('jenisIzin');
        $izin->update(['id_status' => StatusPengajuan::DISETUJUI]);

        $statusPresensiId = StatusPresensi::IZIN;
        if ($izin->id_jenis_izin == JenisIzin::SAKIT) {
            $statusPresensiId = StatusPresensi::SAKIT;
        }

        $startDate = Carbon::parse($izin->tanggal_mulai, 'Asia/Jakarta');
        $endDate = Carbon::parse($izin->tanggal_selesai, 'Asia/Jakarta');

        while ($startDate->lte($endDate)) {
            Presensi::updateOrCreate(
                [
                    'id_user' => $izin->id_user,
                    'tanggal' => $startDate->format('Y-m-d'),
                ],
                [
                    'id_status' => $statusPresensiId,
                    'jam_masuk' => null,
                    'jam_pulang' => null,
                    'id_validasi' => StatusValidasi::VALID,
                    'alasan_telat' => $izin->jenisIzin->nama_izin . ': ' . $izin->alasan,
                ]
            );
            $startDate->addDay();
        }

        if ($izin->id_jenis_izin == JenisIzin::CUTI) {
            $user = \App\Models\User::find($izin->id_user, ['*']);
            $jumlahHari = Carbon::parse($izin->tanggal_mulai)->diffInDays(Carbon::parse($izin->tanggal_selesai)) + 1;
            
            if (($user->sisa_cuti ?? 0) < $jumlahHari) {
                throw new \Exception("Sisa cuti pegawai tidak mencukupi saat ini ({$user->sisa_cuti} hari).");
            }
            
            $newSisa = max(0, ($user->sisa_cuti ?? 0) - $jumlahHari);
            $user->update(['sisa_cuti' => $newSisa]);
        }
    }
}
