<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\AttendanceCorrection;
use App\Models\Attendance;
use App\Services\AttendanceCorrectionService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;

class AttendanceCorrectionController extends Controller
{
    protected AttendanceCorrectionService $correctionService;

    public function __construct(AttendanceCorrectionService $correctionService)
    {
        $this->correctionService = $correctionService;
    }

    /**
     * Get correction settings and eligible dates
     */
    public function settings(): JsonResponse
    {
        $user = Auth::user();
        $company = $user->company;

        return response()->json([
            'success' => true,
            'data' => [
                'backdate_enabled' => $company->backdate_enabled ?? false,
                'quota' => $this->correctionService->getQuotaInfo($user),
                'correction_types' => AttendanceCorrection::CORRECTION_TYPES,
            ],
        ]);
    }

    /**
     * Get eligible attendances for correction
     */
    public function eligibleAttendances(Request $request): JsonResponse
    {
        $user = Auth::user();
        $month = $request->input('month', now()->month);
        $year = $request->input('year', now()->year);

        $attendances = Attendance::where('user_id', $user->id)
            ->whereMonth('date', $month)
            ->whereYear('date', $year)
            ->whereNotNull('check_in_time')
            ->orderBy('date', 'desc')
            ->get()
            ->map(function ($attendance) {
                return [
                    'id' => $attendance->id,
                    'date' => $attendance->date->format('Y-m-d'),
                    'date_formatted' => $attendance->date->translatedFormat('l, d F Y'),
                    'check_in_time' => $attendance->check_in_time?->format('H:i'),
                    'check_out_time' => $attendance->check_out_time?->format('H:i'),
                    'work_duration' => $attendance->work_duration,
                    'type' => $attendance->type,
                    'status' => $attendance->status,
                ];
            });

        return response()->json([
            'success' => true,
            'data' => [
                'attendances' => $attendances,
            ],
        ]);
    }

    /**
     * Get user's correction history
     */
    public function history(Request $request): JsonResponse
    {
        $user = Auth::user();
        $perPage = $request->input('per_page', 15);

        $corrections = AttendanceCorrection::forUser($user->id)
            ->with(['attendance', 'approver'])
            ->orderBy('created_at', 'desc')
            ->paginate($perPage);

        $data = $corrections->map(function ($correction) {
            return $this->formatCorrection($correction);
        });

        return response()->json([
            'success' => true,
            'data' => [
                'corrections' => $data,
                'pagination' => [
                    'current_page' => $corrections->currentPage(),
                    'last_page' => $corrections->lastPage(),
                    'per_page' => $corrections->perPage(),
                    'total' => $corrections->total(),
                ],
            ],
        ]);
    }

    /**
     * Create a new correction request
     */
    public function store(Request $request): JsonResponse
    {
        // Normalize field names from mobile app
        // Mobile sends: attendance_id, corrected_check_in_time, corrected_check_out_time
        // Backend expects: target_date, corrected_check_in, corrected_check_out
        $data = $request->all();

        // Handle attendance_id -> get target_date from attendance record
        if (isset($data['attendance_id']) && !isset($data['target_date'])) {
            $attendance = Attendance::find($data['attendance_id']);
            if ($attendance) {
                $data['target_date'] = $attendance->date->format('Y-m-d');
            }
        }

        // Normalize time field names (mobile uses _time suffix)
        if (isset($data['corrected_check_in_time']) && !isset($data['corrected_check_in'])) {
            $data['corrected_check_in'] = $data['corrected_check_in_time'];
        }
        if (isset($data['corrected_check_out_time']) && !isset($data['corrected_check_out'])) {
            $data['corrected_check_out'] = $data['corrected_check_out_time'];
        }

        // Convert empty strings to null for time fields
        if (isset($data['corrected_check_in']) && $data['corrected_check_in'] === '') {
            $data['corrected_check_in'] = null;
        }
        if (isset($data['corrected_check_out']) && $data['corrected_check_out'] === '') {
            $data['corrected_check_out'] = null;
        }

        $validator = Validator::make($data, [
            'target_date' => 'required|date',
            'correction_type' => 'required|in:check_in,check_out,both,duration',
            'corrected_check_in' => 'nullable|date_format:H:i',
            'corrected_check_out' => 'nullable|date_format:H:i',
            'corrected_duration' => 'nullable|integer|min:0',
            'reason' => 'required|string|max:500',
            'simulated_request_at' => 'nullable|date',
        ]);

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

        try {
            $correction = $this->correctionService->createRequest(
                $data,
                Auth::user()
            );

            return response()->json([
                'success' => true,
                'message' => $correction->is_auto_approved
                    ? 'Koreksi berhasil diproses'
                    : 'Pengajuan koreksi berhasil dikirim',
                'data' => [
                    'correction' => $this->formatCorrection($correction),
                ],
            ], 201);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 400);
        }
    }

    /**
     * Get single correction detail
     */
    public function show(AttendanceCorrection $correction): JsonResponse
    {
        $user = Auth::user();

        // Check ownership
        if ($correction->user_id !== $user->id) {
            return response()->json([
                'success' => false,
                'message' => 'Tidak memiliki akses',
            ], 403);
        }

        return response()->json([
            'success' => true,
            'data' => [
                'correction' => $this->formatCorrection($correction->load(['attendance', 'approver'])),
            ],
        ]);
    }

    /**
     * Cancel a pending correction
     */
    public function cancel(AttendanceCorrection $correction): JsonResponse
    {
        $user = Auth::user();

        // Check ownership
        if ($correction->user_id !== $user->id) {
            return response()->json([
                'success' => false,
                'message' => 'Tidak memiliki akses',
            ], 403);
        }

        if (!$correction->isPending()) {
            return response()->json([
                'success' => false,
                'message' => 'Koreksi ini sudah diproses dan tidak dapat dibatalkan',
            ], 400);
        }

        $correction->delete();

        return response()->json([
            'success' => true,
            'message' => 'Pengajuan koreksi berhasil dibatalkan',
        ]);
    }

    /**
     * Admin: Get pending corrections
     */
    public function adminPending(Request $request): JsonResponse
    {
        $user = Auth::user();
        $company = $user->company;

        $corrections = AttendanceCorrection::forCompany($company->id)
            ->pending()
            ->with(['user', 'attendance'])
            ->orderBy('created_at', 'desc')
            ->paginate($request->input('per_page', 15));

        $data = $corrections->map(function ($correction) {
            return $this->formatCorrection($correction);
        });

        return response()->json([
            'success' => true,
            'data' => [
                'corrections' => $data,
                'pagination' => [
                    'current_page' => $corrections->currentPage(),
                    'last_page' => $corrections->lastPage(),
                    'total' => $corrections->total(),
                ],
            ],
        ]);
    }

    /**
     * Admin: Approve a correction
     */
    public function adminApprove(AttendanceCorrection $correction): JsonResponse
    {
        $user = Auth::user();

        // Check company match
        if ($correction->company_id !== $user->company_id) {
            return response()->json([
                'success' => false,
                'message' => 'Tidak memiliki akses',
            ], 403);
        }

        try {
            $correction = $this->correctionService->approve($correction, $user);

            return response()->json([
                'success' => true,
                'message' => 'Koreksi berhasil disetujui',
                'data' => [
                    'correction' => $this->formatCorrection($correction),
                ],
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 400);
        }
    }

    /**
     * Admin: Reject a correction
     */
    public function adminReject(Request $request, AttendanceCorrection $correction): JsonResponse
    {
        $user = Auth::user();

        // Check company match
        if ($correction->company_id !== $user->company_id) {
            return response()->json([
                'success' => false,
                'message' => 'Tidak memiliki akses',
            ], 403);
        }

        try {
            $correction = $this->correctionService->reject(
                $correction,
                $user,
                $request->input('rejection_reason')
            );

            return response()->json([
                'success' => true,
                'message' => 'Koreksi berhasil ditolak',
                'data' => [
                    'correction' => $this->formatCorrection($correction),
                ],
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 400);
        }
    }

    /**
     * Format correction for API response
     */
    protected function formatCorrection(AttendanceCorrection $correction): array
    {
        return [
            'id' => $correction->id,
            'user_id' => $correction->user_id,
            'user_name' => $correction->user?->name,
            'attendance_id' => $correction->attendance_id,
            'target_date' => $correction->target_date->format('Y-m-d'),
            'target_date_formatted' => $correction->target_date->translatedFormat('l, d F Y'),
            'correction_type' => $correction->correction_type,
            'correction_type_label' => $correction->correction_type_label,
            'original_check_in' => $correction->original_check_in,
            'original_check_out' => $correction->original_check_out,
            'original_duration' => $correction->original_duration,
            'corrected_check_in' => $correction->corrected_check_in,
            'corrected_check_out' => $correction->corrected_check_out,
            'corrected_duration' => $correction->corrected_duration,
            'reason' => $correction->reason,
            'status' => $correction->status,
            'status_label' => $correction->status_label,
            'is_auto_approved' => $correction->is_auto_approved,
            'approver_name' => $correction->approver?->name,
            'approved_at' => $correction->approved_at?->toIso8601String(),
            'approved_at_formatted' => $correction->approved_at?->translatedFormat('d M Y H:i'),
            'rejection_reason' => $correction->rejection_reason,
            'created_at' => $correction->created_at->toIso8601String(),
            'created_at_formatted' => $correction->created_at->translatedFormat('d M Y H:i'),
        ];
    }
}
