<?php

namespace App\Http\Controllers;

use App\Models\Roster;
use App\Services\ApiResponseCache;
use App\Support\RosterData;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class RosterHistoryController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        $perPage = min(max((int) $request->integer('per_page', 25), 1), 100);
        $query = Roster::query()
            ->with('user:id,name,team')
            ->latest('roster_date')
            ->latest('updated_at');

        if ($request->filled('user') && $request->string('user')->toString() !== 'All Users') {
            $query->whereHas('user', fn ($users) => $users->where('name', $request->string('user')->toString()));
        }

        if ($request->filled('team')) {
            $query->where('team', RosterData::normalizeTeam($request->string('team')->toString()));
        }

        if ($request->filled('from_date')) {
            $query->whereDate('roster_date', '>=', $request->string('from_date')->toString());
        }

        if ($request->filled('to_date')) {
            $query->whereDate('roster_date', '<=', $request->string('to_date')->toString());
        }

        $paginator = $query->paginate($perPage);
        $paginator->setCollection(
            $paginator->getCollection()->map(fn (Roster $roster) => $this->toHistoryRow($roster))
        );

        return response()->json($paginator);
    }

    public function update(Request $request, Roster $roster, ApiResponseCache $apiResponseCache): JsonResponse
    {
        $payload = $request->validate([
            'roster_date' => ['required', 'date'],
            'holiday' => ['nullable', 'boolean'],
            'shift1StartDate' => ['nullable', 'string', 'max:32'],
            'shift1StartTime' => ['nullable', 'string', 'max:32'],
            'shift1EndDate' => ['nullable', 'string', 'max:32'],
            'shift1EndTime' => ['nullable', 'string', 'max:32'],
            'shift2StartDate' => ['nullable', 'string', 'max:32'],
            'shift2StartTime' => ['nullable', 'string', 'max:32'],
            'shift2EndDate' => ['nullable', 'string', 'max:32'],
            'shift2EndTime' => ['nullable', 'string', 'max:32'],
            'shift3StartDate' => ['nullable', 'string', 'max:32'],
            'shift3StartTime' => ['nullable', 'string', 'max:32'],
            'shift3EndDate' => ['nullable', 'string', 'max:32'],
            'shift3EndTime' => ['nullable', 'string', 'max:32'],
        ]);

        $rosterDate = RosterData::normalizeDate($payload['roster_date'], $roster->roster_date?->toDateString() ?? now()->toDateString());
        $attributes = RosterData::buildRosterAttributes($payload, $rosterDate, $roster->team);

        $savedRoster = DB::transaction(function () use ($roster, $rosterDate, $attributes) {
            $existingRoster = Roster::query()
                ->where('user_id', $roster->user_id)
                ->whereDate('roster_date', $rosterDate)
                ->whereKeyNot($roster->id)
                ->first();

            if ($existingRoster) {
                $existingRoster->fill([
                    ...$attributes,
                    'roster_date' => $rosterDate,
                ])->save();

                $roster->delete();

                return $existingRoster->fresh(['user:id,name,team']);
            }

            $roster->fill([
                ...$attributes,
                'roster_date' => $rosterDate,
            ])->save();

            return $roster->fresh(['user:id,name,team']);
        });
        $apiResponseCache->invalidateGroups(['rosters']);

        return response()->json([
            'message' => 'Roster updated successfully.',
            'entry' => $this->toHistoryRow($savedRoster),
        ]);
    }

    public function destroy(Roster $roster, ApiResponseCache $apiResponseCache): JsonResponse
    {
        $roster->delete();
        $apiResponseCache->invalidateGroups(['rosters']);

        return response()->json([
            'message' => 'Roster deleted successfully.',
        ]);
    }

    private function toHistoryRow(Roster $roster): array
    {
        return [
            'id' => $roster->id,
            'userId' => $roster->user_id,
            'user' => $roster->user?->name ?? 'Unknown user',
            'team' => RosterData::normalizeTeam($roster->team),
            'rosterDate' => $roster->roster_date?->toDateString(),
            'shift1Start' => RosterData::formatDateTime($roster->shift1_start),
            'shift1End' => RosterData::formatDateTime($roster->shift1_end),
            'shift2Start' => RosterData::formatDateTime($roster->shift2_start),
            'shift2End' => RosterData::formatDateTime($roster->shift2_end),
            'shift3Start' => RosterData::formatDateTime($roster->shift3_start),
            'shift3End' => RosterData::formatDateTime($roster->shift3_end),
            'totalHours' => RosterData::formatHours($roster->total_hours),
            'holiday' => $roster->is_holiday ? 'Holiday' : 'No',
            'holidayValue' => (bool) $roster->is_holiday,
            'updatedAt' => $roster->updated_at?->format('Y-m-d h:i A') ?? '-',
            'shift1StartDate' => $roster->shift1_start?->toDateString() ?? '',
            'shift1StartTime' => $roster->shift1_start?->format('h:i A') ?? '09:00 AM',
            'shift1EndDate' => $roster->shift1_end?->toDateString() ?? '',
            'shift1EndTime' => $roster->shift1_end?->format('h:i A') ?? '09:00 AM',
            'shift2StartDate' => $roster->shift2_start?->toDateString() ?? '',
            'shift2StartTime' => $roster->shift2_start?->format('h:i A') ?? '09:00 AM',
            'shift2EndDate' => $roster->shift2_end?->toDateString() ?? '',
            'shift2EndTime' => $roster->shift2_end?->format('h:i A') ?? '09:00 AM',
            'shift3StartDate' => $roster->shift3_start?->toDateString() ?? '',
            'shift3StartTime' => $roster->shift3_start?->format('h:i A') ?? '09:00 AM',
            'shift3EndDate' => $roster->shift3_end?->toDateString() ?? '',
            'shift3EndTime' => $roster->shift3_end?->format('h:i A') ?? '09:00 AM',
        ];
    }
}
