<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use App\Models\PengajuanUkt;
use App\Models\PengajuanDetail;
use App\Models\Kriteria;   
use App\Models\Form;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\DB;
use App\Notifications\PengajuanValidNotification;
use App\Notifications\PengajuanDitolakNotification;
use Illuminate\Support\Facades\Log;
use App\Models\RankingFile;

class AdminPengajuanController extends Controller
{
    // Status mapping for consistent status values
    const STATUS_MAPPING = [
        'diterima' => 'valid',
        'menunggu' => 'menunggu',
        'ditolak' => 'tidak valid'
    ];

    const REJECTION_REASONS_BY_CRITERIA = [
        'Pekerjaan Orang Tua' => [
            'Surat keterangan kerja tidak valid',
            'Tidak ada bukti usaha (untuk wiraswasta)',
            'Dokumen kadaluarsa',
            'Dokumen tidak sesuai',
            'Lainnya'
        ],
        'Penghasilan Orang Tua' => [
            'Jumlah gaji tidak sesuai',
            'Slip gaji tidak terbaca',
            'Dokumen tidak sesuai',
            'Lainnya'
        ],
        'Status Orang Tua' => [
            'Dokumen tidak sesuai',
            'Dokumen tidak terbaca',
            'Tidak ada bukti surat perceraian',
            'Tidak ada bukti surat keterangan kematian',
            'Lainnya'
        ],
        'Tanggungan Orang Tua' => [
            'Kartu Keluarga tidak terbaca',
            'Jumlah tanggungan tidak sesuai',
            'Dokumen tidak sesuai',
            'Lainnya'
        ],
        'Hunian' => [
            'Bukti kepemilikan tidak valid',
            'Dokumen tidak terbaca',
            'Dokumen tidak sesuai',
            'Lainnya'
        ],
        'Kendaraan' => [
            'Dokumen tidak sesuai',
            'STNK tidak valid',
            'STNK tidak terbaca',
            'Lainnya'
        ],
        'IPK' => [
            'KHS tidak valid',
            'KHS tidak terbaca',
            'IPK tidak sesuai dengan sistem',
            'Lainnya'
        ],
        'Semester' => [
            'KHS tidak valid',
            'KHS tidak terbaca',
            'Semester tidak sesuai dengan sistem',
            'Lainnya'
        ],
        'Slip Pembayaran UKT' => [
            'Dokumen tidak terbaca',
            'Nominal tidak sesuai',
            'Slip pembayaran tidak sesuai',
            'Lainnya'
        ]
    ];


    /**
     * Display list of UKT submissions with filtering
     */
    public function index()
    {
       $statusFilter = $this->mapStatusFilter(request('status'));

    $query = PengajuanUkt::with(['mahasiswa.user:id,name','form'])
        ->withCount('details');

    if (request()->has('status_form_id') && request('status_form_id') != '') {
        $query->where('status_form_id', request('status_form_id')); 
    }

    // Filter by jenis form
    if (request()->has('jenis_form') && request('jenis_form') != '') {
        $query->whereHas('form', function($q) {
            $q->where('jenis_form', request('jenis_form'));
        });
    }

    if ($statusFilter) {
        $query->where('status_validasi', $statusFilter);
    }

    $pengajuan = $query->latest()->paginate(10);

    $forms = Form::select('id', 'nama_form')
        ->orderBy('created_at', 'desc')
        ->get();

    $stats = [
        'totalPengajuan' => PengajuanUkt::count(),
        'valid' => PengajuanUkt::valid()->count(),
        'menunggu' => PengajuanUkt::menunggu()->count(),
        'tidak valid' => PengajuanUkt::tidakValid()->count() 
    ];
    
    return view('admin.pengajuan.index', compact('pengajuan', 'stats', 'forms'));
}

    /**
     * Map status filter to consistent values
     */
    protected function mapStatusFilter($status)
    {
        return self::STATUS_MAPPING[$status] ?? $status;
    }

    public function detail($id)
    {
        $pengajuan = PengajuanUkt::with([
            'details' => function($query) {
                $query->select([
                    'id', 
                    'pengajuan_ukt_id', 
                    'kriteria', 
                    'subkriteria_text', 
                    'file_dokumen', 
                    'verified', 
                    'rejection_reason',
                    'verified_by',
                    'verified_at'
                ])->with(['verifier:id,name']);
            },
            'mahasiswa.user:id,name'
        ])->select([
            'id',
            'mahasiswa_id',
            'jenis_pengajuan',
            'alasan_pengajuan',
            'ukt_saat_ini',
            'status_validasi',
            'created_at',
            'updated_at'
        ])->findOrFail($id);

        return view('admin.pengajuan.detail', [
            'pengajuan' => $pengajuan,
            'rejectionReasonsByCriteria' => self::REJECTION_REASONS_BY_CRITERIA
        ]);
    }

    public function bulkVerify(Request $request, $id)
    {
        if (auth()->user()->role !== 'karyawan') {
            abort(403, 'Hanya karyawan yang dapat melakukan verifikasi');
        }

        $data = $request->all();

        $rules = [
            'valid' => 'required|array',
            'valid.*' => 'in:0,1',
            'alasan' => 'nullable|array',
            'alasan_lainnya' => 'nullable|array',
        ];

        foreach ($data['valid'] as $detailId => $value) {
            if ((string) $value === '0') {
                $rules["alasan.$detailId"] = 'required|string';
                if (isset($data['alasan'][$detailId]) && $data['alasan'][$detailId] === 'Lainnya') {
                    $rules["alasan_lainnya.$detailId"] = 'required|string';
                }
            }
        }

        $validator = Validator::make($data, $rules);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Validasi gagal',
                'errors' => $validator->errors()
            ], 422);
        }

        DB::beginTransaction();

        try {
            $pengajuan = PengajuanUkt::with(['details', 'mahasiswa.user'])->findOrFail($id);

            foreach ($pengajuan->details as $detail) {
                $isValid = $request->input("valid.{$detail->id}") == '1';
                $alasan = $request->input("alasan.{$detail->id}");
                $alasanLainnya = $request->input("alasan_lainnya.{$detail->id}");

                $rejectionReason = $this->processRejectionReason($alasan, $alasanLainnya);

                $detail->update([
                    'verified' => $isValid,
                    'verified_by' => auth()->id(),
                    'verified_at' => now(),
                    'rejection_reason' => $isValid ? null : $rejectionReason,
                ]);
            }

            $status = $this->updatePengajuanStatus($pengajuan);

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Validasi dokumen berhasil disimpan! Status: ' . ($status === 'valid' ? 'Valid' : 'Tidak Valid'),
                'redirect' => route('admin.pengajuan.detail', $id)
            ]);

        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'success' => false,
                'message' => 'Gagal memvalidasi pengajuan: ' . $e->getMessage()
            ], 500);
        }
    }

   public function revalidate(Request $request, $id)
{
    $validator = Validator::make($request->all(), [
        'valid' => 'required|array',
        'valid.*' => 'in:0,1',
        'alasan' => 'required_without:valid.*|array',
        'alasan_lainnya' => 'required_if:alasan.*,Lainnya|array'
    ]);

    if ($validator->fails()) {
        return response()->json([
            'success' => false,
            'message' => 'Validasi gagal',
            'errors' => $validator->errors()
        ], 422);
    }

    DB::beginTransaction();

    try {
        $pengajuan = PengajuanUkt::with('details')->findOrFail($id);
        $changesMade = false;

        foreach ($request->input('valid') as $detailId => $isValid) {
            $detail = $pengajuan->details->firstWhere('id', $detailId);
            if (!$detail) continue;

            $alasan = $request->input("alasan.{$detailId}");
            $alasanLainnya = $request->input("alasan_lainnya.{$detailId}");
            $rejectionReason = $isValid ? null : $this->processRejectionReason($alasan, $alasanLainnya);

            // Check if changes are needed
            if ($detail->verified != $isValid || $detail->rejection_reason != $rejectionReason) {
                $detail->verified = $isValid;
                $detail->rejection_reason = $rejectionReason;
                $detail->verified_by = auth()->id();
                $detail->verified_at = now();
                $detail->save();
                $changesMade = true;
            }
        }

        if ($changesMade) {
            $status = $this->updatePengajuanStatus($pengajuan);
            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Revalidasi berhasil disimpan',
                'redirect' => route('admin.pengajuan.detail', $id)
            ]);
        }

        DB::commit();
        return response()->json([
            'success' => true,
            'message' => 'Tidak ada perubahan yang dilakukan',
            'redirect' => route('admin.pengajuan.detail', $id)
        ]);

    } catch (\Exception $e) {
        DB::rollBack();
        return response()->json([
            'success' => false,
            'message' => 'Gagal menyimpan revalidasi: ' . $e->getMessage()
        ], 500);
    }
}

    public function verifyUkt(Request $request, $id)
    {
        $validator = Validator::make($request->all(), [
            'valid_ukt' => 'required|boolean',
            'alasan_ukt' => 'required_if:valid_ukt,0|nullable|string',
            'alasan_lainnya_ukt' => 'required_if:alasan_ukt,Lainnya|nullable|string'
        ]);

        if ($validator->fails()) {
            return back()
                ->withErrors($validator)
                ->withInput();
        }

        DB::beginTransaction();

        try {
            $pengajuan = PengajuanUkt::with(['details', 'mahasiswa.user'])
                ->findOrFail($id);

            $alasanUkt = $this->processRejectionReason(
                $request->alasan_ukt,
                $request->alasan_lainnya_ukt
            );

            $pengajuan->update([
                'file_ukt_valid' => $request->valid_ukt,
                'file_ukt_alasan' => $request->valid_ukt ? null : $alasanUkt,
                'updated_at' => now()
            ]);

            $this->updatePengajuanStatus($pengajuan);

            DB::commit();

            return redirect()
                ->route('admin.pengajuan.detail', $id)
                ->with('success', 'Verifikasi Slip UKT berhasil disimpan');

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

    protected function processRejectionReason($alasan, $alasanLainnya)
    {
        if ($alasan === 'Lainnya') {
            return 'Lainnya: ' . $alasanLainnya;
        }
        return $alasan;
    }

    protected function updatePengajuanStatus($pengajuan)
    {
        $invalidCount = $pengajuan->details()
            ->where('verified', false)
            ->orWhereNotNull('rejection_reason')
            ->count();

        $status = $invalidCount === 0 ? 'valid' : 'tidak valid';
        
        $pengajuan->update([
            'status_validasi' => $status,
            'updated_at' => now()
        ]);
        
        $this->sendNotification($pengajuan, $status);
        
        return $status;
    }

    private function sendNotification($pengajuan, $status)
    {
        try {
            if ($status === 'valid') {
                $pengajuan->mahasiswa->user->notify(new PengajuanValidNotification($pengajuan));
            } else {
                $reasons = $pengajuan->details()
                    ->whereNotNull('rejection_reason')
                    ->pluck('rejection_reason', 'kriteria')
                    ->map(function($reason, $kriteria) {
                        return "$kriteria: " . (strpos($reason, 'Lainnya:') === 0 ? substr($reason, 8) : $reason);
                    })
                    ->implode("\n");
                
                $pengajuan->mahasiswa->user->notify(
                    new PengajuanDitolakNotification($pengajuan, $reasons)
                );
            }
        } catch (\Exception $e) {
            // Silent fail for notifications
        }
    }

    public function destroy($id)
    {
        DB::beginTransaction();
        try {
            $pengajuan = PengajuanUkt::with(['details', 'hasilPenilaian'])->findOrFail($id);

            foreach ($pengajuan->details as $detail) {
                if ($detail->file_dokumen) {
                    $filePath = 'public/' . ltrim($detail->file_dokumen, '/');
                    if (Storage::exists($filePath)) {
                        Storage::delete($filePath);
                    }
                }
            }

            $pengajuan->hasilPenilaian()->delete();
            $pengajuan->details()->delete();
            $pengajuan->delete();

            DB::commit();

            return redirect()->route('admin.pengajuan')
                   ->with('success', 'Pengajuan berhasil dihapus');

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

    public function storeRankingReport(Request $request)
    {
        $request->validate([
            'ranking_file' => 'required|file|mimes:pdf|max:10240'
        ]);

        DB::beginTransaction();
        try {
            $existingFile = RankingFile::first();
            if ($existingFile) {
                Storage::delete('public/' . $existingFile->path);
                $existingFile->delete();
            }

            $file = $request->file('ranking_file');
            $path = $file->store('public/ranking_files');

            RankingFile::create([
                'path' => str_replace('public/', '', $path),
                'uploaded_by' => auth()->id()
            ]);

            DB::commit();

            return redirect()->route('admin.pengajuan')
                ->with('report_status', [
                    'type' => 'success',
                    'message' => 'Laporan ranking berhasil dikirim ke mahasiswa!'
                ]);

        } catch (\Exception $e) {
            DB::rollBack();
            return back()->with('report_status', [
                'type' => 'danger',
                'message' => 'Gagal mengunggah laporan ranking: ' . $e->getMessage()
            ]);
        }
    }

    public function deleteRankingReport()
    {
        DB::beginTransaction();
        try {
            $rankingFile = RankingFile::first();
            
            if ($rankingFile) {
                Storage::delete('public/' . $rankingFile->path);
                $rankingFile->delete();
                
                $message = 'Laporan ranking berhasil dibatalkan!';
                $type = 'warning';
            } else {
                $message = 'Tidak ada laporan ranking aktif';
                $type = 'info';
            }

            DB::commit();

            return redirect()->route('admin.pengajuan')
                ->with('report_status', [
                    'type' => $type,
                    'message' => $message
                ]);

        } catch (\Exception $e) {
            DB::rollBack();
            return back()->with('report_status', [
                'type' => 'danger',
                'message' => 'Gagal membatalkan laporan ranking: ' . $e->getMessage()
            ]);
        }
    }

    public function viewRankingReport($id)
    {
        $rankingFile = RankingFile::findOrFail($id);
        
        $filePath = storage_path('app/public/' . $rankingFile->path);
        
        if (!file_exists($filePath)) {
            abort(404, 'File laporan tidak ditemukan');
        }

        return response()->download(
            $filePath,
            'Laporan-UKT-'.$rankingFile->created_at->format('Y-m-d').'.pdf'
        );
    }
}