<?php

namespace App\Http\Controllers;

use App\Models\Holiday;
use App\Models\ExcelUploadLog;
use App\Traits\ExcelUploadTrait;
use Illuminate\Http\Request;
use Carbon\Carbon;

class HolidaysController extends Controller
{
    use ExcelUploadTrait; 
    public function index(Request $request)
    {
        if ($request->ajax()) {
            $query = Holiday::select('m_holidays.*')
                ->where('delete_flag', false);

            // Filter by year if specified
            if ($request->has('year') && $request->year) {
                $query->forYear($request->year);
            } else {
                // Default to current year
                $query->forYear(Carbon::now()->year);
            }

            // Searching
            if ($request->has('search') && $request->search['value'] != '') {
                $search = $request->search['value'];
                $query->where(function ($q) use ($search) {
                    $q->where('name', 'ilike', "%{$search}%")
                        ->orWhere('type', 'ilike', "%{$search}%")
                        ->orWhere('description', 'ilike', "%{$search}%");
                });
            }

            $total = $query->count();

            // Sorting
            $columns = ['id', 'name', 'date', 'type', 'is_recurring', 'is_active'];
            $orderColumn = $columns[$request->order[0]['column']] ?? 'date';
            $orderDir = $request->order[0]['dir'] ?? 'asc';

            $query->orderBy($orderColumn, $orderDir);

            // Pagination
            $start = $request->start;
            $length = $request->length;
            $data = $query->skip($start)->take($length)->get();

            // Format data
            $result = [];
            $no = $start + 1;
            foreach ($data as $row) {
                $statusBadge = $row->is_active ? '<span class="badge badge-success">Active</span>' : '<span class="badge badge-secondary">Inactive</span>';
                $typeBadge = '<span class="badge ' . $row->type_badge . '">' . $row->type . '</span>';
                $recurringBadge = $row->is_recurring ? '<span class="badge badge-info">Yes</span>' : '<span class="badge badge-secondary">No</span>';
                
                $dateInfo = $row->formatted_date;
                if ($row->isToday()) {
                    $dateInfo .= ' <span class="badge badge-secondary">TODAY</span>';
                } elseif ($row->isFuture() && $row->days_until !== null && $row->days_until <= 7) {
                    $dateInfo .= ' <span class="badge badge-info">' . $row->days_until . ' days</span>';
                }
                
                $result[] = [
                    $no++,
                    '<a href="' . route('holidays.show', $row->id) . '">' . $row->name . '</a>',
                    $dateInfo,
                    $typeBadge,
                    $recurringBadge,
                    $row->description ?: '-',
                    $statusBadge,
                ];
            }

            return response()->json([
                "draw" => intval($request->draw),
                "recordsTotal" => $total,
                "recordsFiltered" => $total,
                "data" => $result,
            ]);
        }

        // Get available years for filter
        $years = Holiday::active()
            ->selectRaw('EXTRACT(YEAR FROM date) as year')
            ->distinct()
            ->orderBy('year', 'desc')
            ->pluck('year')
            ->toArray();
            
        if (empty($years)) {
            $years = [Carbon::now()->year];
        }

        return view('m-holidays.index', [
            'variables' => $this->variables([
                'years' => $years,
                'current_year' => Carbon::now()->year
            ])
        ]);
    }

    public function create()
    {
        $variables['judul'] = 'Add Holiday';
        $variables['types'] = Holiday::getTypes();
        $variables['recurring_types'] = Holiday::getRecurringTypes();
        
        return view('m-holidays.form', [
            'data' => json_decode(json_encode(array('id' => 0))),
            'variables' => $this->variables($variables)
        ]);
    }

    public function edit(Holiday $holiday)
    {
        $variables['judul'] = 'Edit Holiday';
        $variables['types'] = Holiday::getTypes();
        $variables['recurring_types'] = Holiday::getRecurringTypes();
        
        return view('m-holidays.form', [
            'data' => $holiday,
            'variables' => $this->variables($variables)
        ]);
    }

    public function store(Request $request, $prm_id = null)
    {
        $holiday = null;
        if ($prm_id)
            $holiday = Holiday::findOrFail($prm_id);

        $rules = [
            'name' => 'required|string|max:255',
            'date' => 'required|date',
            'type' => 'required|in:' . implode(',', array_keys(Holiday::getTypes())),
            'description' => 'nullable|string',
            'is_recurring' => 'boolean',
            'recurring_type' => 'required|in:' . implode(',', array_keys(Holiday::getRecurringTypes())),
            'is_active' => 'boolean'
        ];

        $messages = [];
        $saveData = $request->validate($rules, $messages);

        // Set default values
        $saveData['is_recurring'] = $request->has('is_recurring');
        $saveData['is_active'] = $request->has('is_active');

        // If not recurring, set recurring_type to None
        if (!$saveData['is_recurring']) {
            $saveData['recurring_type'] = Holiday::RECURRING_NONE;
        }

        try {
            if ($holiday) {
                $holiday->update(array_merge($saveData, [
                    'updated_by' => $this->logged_user_id,
                ]));
            } else {
                Holiday::create(array_merge($saveData, [
                    'delete_flag' => false,
                    'created_by' => $this->logged_user_id,
                    'updated_by' => $this->logged_user_id,
                ]));
            }

            $notif = $holiday ? 'Updated successfully.' : 'Successfully created.';
            return response()->json(['success', $notif]);
            
        } catch (\Exception $e) {
            $notif = $this->getErrorCatch($e->getMessage());
            return response()->json(['warning', $notif]);
        }
    }

    public function show(Holiday $holiday)
    {
        $holiday->load(['creator', 'modificator']);
        $variables['judul'] = 'View Holiday: ' . $holiday->name;
        return view('m-holidays.show', [
            'data' => $holiday,
            'variables' => $this->variables($variables)
        ]);
    }

    public function destroy(Holiday $holiday)
    {
        $holiday->update([
            'delete_flag' => true,
            'updated_by' => $this->logged_user_id
        ]);

        return redirect()->route('holidays.index')
            ->with('success', 'Successfully deleted');
    }

    // API method to check if date is holiday
    public function checkHoliday(Request $request)
    {
        $date = $request->get('date');
        
        if (!$date) {
            return response()->json(['error' => 'Date parameter required'], 400);
        }

        $isHoliday = Holiday::isHoliday($date);
        $holiday = null;
        
        if ($isHoliday) {
            $holiday = Holiday::enabled()
                ->where('date', Carbon::parse($date)->format('Y-m-d'))
                ->first();
        }

        return response()->json([
            'date' => $date,
            'is_holiday' => $isHoliday,
            'holiday' => $holiday ? [
                'name' => $holiday->name,
                'type' => $holiday->type,
                'description' => $holiday->description
            ] : null
        ]);
    }

    // API method to get holidays in date range
    public function getHolidaysInRange(Request $request)
    {
        $startDate = $request->get('start_date');
        $endDate = $request->get('end_date');
        
        if (!$startDate || !$endDate) {
            return response()->json(['error' => 'start_date and end_date parameters required'], 400);
        }

        $holidays = Holiday::getHolidaysInRange($startDate, $endDate);

        return response()->json([
            'start_date' => $startDate,
            'end_date' => $endDate,
            'holidays' => $holidays->map(function($holiday) {
                return [
                    'name' => $holiday->name,
                    'date' => $holiday->date->format('Y-m-d'),
                    'formatted_date' => $holiday->formatted_date,
                    'type' => $holiday->type,
                    'description' => $holiday->description
                ];
            })
        ]);
    }

    // Method to generate recurring holidays for next year
    public function generateRecurringHolidays(Request $request)
    {
        $targetYear = $request->get('year', Carbon::now()->addYear()->year);
        
        $recurringHolidays = Holiday::enabled()
            ->where('is_recurring', true)
            ->where('recurring_type', '!=', Holiday::RECURRING_NONE)
            ->get();

        $generated = [];
        
        foreach ($recurringHolidays as $holiday) {
            $newHolidayData = $holiday->generateRecurringHoliday($targetYear);
            
            if ($newHolidayData) {
                // Check if holiday already exists for that date
                $exists = Holiday::where('date', $newHolidayData['date'])
                    ->where('delete_flag', false)
                    ->exists();
                    
                if (!$exists) {
                    $newHoliday = Holiday::create(array_merge($newHolidayData, [
                        'created_by' => $this->logged_user_id,
                        'updated_by' => $this->logged_user_id,
                    ]));
                    
                    $generated[] = $newHoliday;
                }
            }
        }

        return response()->json([
            'target_year' => $targetYear,
            'generated_count' => count($generated),
            'holidays' => $generated
        ]);
    }

    private function variables($variables = [])
    {
        $defaultVariables = [
            'header_routes' => '
                <li class="breadcrumb-item">Master Data</li>
                <li class="breadcrumb-item active">Holidays</li>
            ',
            'judul' => 'Holidays'
        ];

        return array_merge($defaultVariables, $variables);
    }

    private function getErrorCatch($e)
    {
        if (strpos($e, '#error#') !== false) {
            $e = explode('#error#', $e);
            $e = $e[1];
        }

        return $e;
    }

    public function downloadTemplate()
    {
        $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();

        // Set header
        $sheet->setCellValue('A1', 'name');
        $sheet->setCellValue('B1', 'date');
        $sheet->setCellValue('C1', 'type');
        $sheet->setCellValue('D1', 'description');
        $sheet->setCellValue('E1', 'is_recurring');
        $sheet->setCellValue('F1', 'recurring_type');
        $sheet->setCellValue('G1', 'is_active');

        // Style header
        $headerStyle = [
            'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']],
            'fill' => ['fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'startColor' => ['rgb' => 'F39C12']],
            'alignment' => ['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER],
        ];
        $sheet->getStyle('A1:G1')->applyFromArray($headerStyle);

        // Set column width
        $sheet->getColumnDimension('A')->setWidth(30);
        $sheet->getColumnDimension('B')->setWidth(15);
        $sheet->getColumnDimension('C')->setWidth(15);
        $sheet->getColumnDimension('D')->setWidth(40);
        $sheet->getColumnDimension('E')->setWidth(12);
        $sheet->getColumnDimension('F')->setWidth(15);
        $sheet->getColumnDimension('G')->setWidth(12);

        // Add example data
        $sheet->setCellValue('A2', 'Tahun Baru');
        $sheet->setCellValue('B2', '2024-01-01');
        $sheet->setCellValue('C2', 'National');
        $sheet->setCellValue('D2', 'Tahun Baru Masehi');
        $sheet->setCellValue('E2', 'Yes');
        $sheet->setCellValue('F2', 'Yearly');
        $sheet->setCellValue('G2', 'Yes');

        $sheet->setCellValue('A3', 'Hari Raya Idul Fitri');
        $sheet->setCellValue('B3', '2024-04-10');
        $sheet->setCellValue('C3', 'Religious');
        $sheet->setCellValue('D3', 'Hari Raya Idul Fitri 1445 H');
        $sheet->setCellValue('E3', 'No');
        $sheet->setCellValue('F3', 'None');
        $sheet->setCellValue('G3', 'Yes');

        // Add notes
        $sheet->setCellValue('A5', 'Catatan:');
        $sheet->setCellValue('A6', '- name: Nama hari libur (wajib)');
        $sheet->setCellValue('A7', '- date: Format YYYY-MM-DD (contoh: 2024-12-25) (wajib)');
        $sheet->setCellValue('A8', '- type: National, Religious, Company, atau Regional (wajib)');
        $sheet->setCellValue('A9', '- description: Deskripsi hari libur (opsional)');
        $sheet->setCellValue('A10', '- is_recurring: Yes atau No (default: No)');
        $sheet->setCellValue('A11', '- recurring_type: None, Yearly, atau Monthly (default: None)');
        $sheet->setCellValue('A12', '- is_active: Yes atau No (default: Yes)');

        $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
        $filename = 'template_holidays_' . date('YmdHis') . '.xlsx';

        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment;filename="' . $filename . '"');
        header('Cache-Control: max-age=0');

        $writer->save('php://output');
        exit;
    }

    public function uploadExcel(Request $request)
    {
        $request->validate([
            'excel_file' => 'required|mimes:xlsx,xls|max:10240',
        ]);

        try {
            $file = $request->file('excel_file');
            
            // Store uploaded file
            $uploadedFilePath = $this->storeUploadedExcel($file, 'holidays');
            
            $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file->getRealPath());
            $sheet = $spreadsheet->getActiveSheet();
            $rows = $sheet->toArray();
            $rows = $this->trimExcelData($rows); // Trim all data to prevent whitespace issues

            // Remove header
            array_shift($rows);

            $inserted = 0;
            $updated = 0;
            $errors = [];
            $totalRows = count($rows);

            foreach ($rows as $index => $row) {
                $rowNumber = $index + 2;

                // Skip empty rows
                if (empty(array_filter($row))) {
                    continue;
                }

                try {
                    // Validate required fields
                    if (empty($row[0]) || empty($row[1]) || empty($row[2])) {
                        $errors[] = ['row' => $rowNumber, 'error' => 'Nama, tanggal, dan tipe wajib diisi'];
                        continue;
                    }

                    // Validate type
                    $validTypes = array_keys(Holiday::getTypes());
                    if (!in_array($row[2], $validTypes)) {
                        $errors[] = ['row' => $rowNumber, 'error' => 'Tipe tidak valid. Harus: ' . implode(', ', $validTypes)];
                        continue;
                    }

                    // Validate date format
                    try {
                        $date = Carbon::parse($row[1])->format('Y-m-d');
                    } catch (\Exception $e) {
                        $errors[] = ['row' => $rowNumber, 'error' => 'Format tanggal tidak valid. Gunakan YYYY-MM-DD'];
                        continue;
                    }

                    // Parse boolean values
                    $isRecurring = strtolower($row[4] ?? 'no') === 'yes';
                    $isActive = strtolower($row[6] ?? 'yes') === 'yes';

                    // Validate recurring_type
                    $recurringType = $row[5] ?? 'None';
                    $validRecurringTypes = array_keys(Holiday::getRecurringTypes());
                    if (!in_array($recurringType, $validRecurringTypes)) {
                        $recurringType = 'None';
                    }

                    // If not recurring, force recurring_type to None
                    if (!$isRecurring) {
                        $recurringType = 'None';
                    }

                    $data = [
                        'name' => $row[0],
                        'date' => $date,
                        'type' => $row[2],
                        'description' => $row[3] ?? null,
                        'is_recurring' => $isRecurring,
                        'recurring_type' => $recurringType,
                        'is_active' => $isActive,
                        'delete_flag' => false,
                        'updated_by' => auth()->id(),
                    ];

                    // Check if exists (by name and date)
                    $existing = Holiday::where('name', $row[0])
                        ->where('date', $date)
                        ->first();

                    if ($existing) {
                        $existing->update($data);
                        $updated++;
                    } else {
                        $data['created_by'] = auth()->id();
                        Holiday::create($data);
                        $inserted++;
                    }
                } catch (\Exception $e) {
                    $errors[] = ['row' => $rowNumber, 'error' => $e->getMessage()];
                }
            }

            // Log upload
            $errorCount = count($errors);
            ExcelUploadLog::create([
                'upload_type' => 'holidays',
                'uploaded_file' => $uploadedFilePath,
                'original_filename' => $file->getClientOriginalName(),
                'total_rows' => $totalRows,
                'success_rows' => $inserted + $updated,
                'error_rows' => $errorCount,
                'error_details' => $errorCount > 0 ? json_encode($errors) : null,
                'status' => $errorCount > 0 ? ($inserted + $updated > 0 ? 'Partial' : 'Failed') : 'Success',
                'uploaded_by' => auth()->id(),
            ]);

            return response()->json([
                'success' => true,
                'message' => "Upload berhasil! Ditambahkan: {$inserted}, Diperbarui: {$updated}",
                'inserted' => $inserted,
                'updated' => $updated,
                'errors' => $errors,
                'uploaded_file' => $uploadedFilePath,
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Upload gagal: ' . $e->getMessage(),
            ], 500);
        }
    }
}