<?php

namespace App\Http\Controllers;

use App\Models\User;
use App\Models\Barber;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;

class BarberAdminController extends Controller
{
    public function index()
    {
        $barbers = Barber::with(['user', 'services'])->get();
        return response()->json($barbers);
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'name' => 'required|string|max:100',
            'email' => 'required|email|unique:users,email',
            'password' => 'required|string|min:6',
            'phone' => 'nullable|string|max:20',
            'bio' => 'nullable|string',
            'specialty' => 'nullable|string|max:100',
            'service_ids' => 'required|array',
            'service_ids.*' => 'exists:services,id',
            'booking_enabled' => 'sometimes|boolean',
            'weekly_time_off' => 'nullable|array',
            'weekly_time_off.*.weekday' => 'required|integer|between:0,6',
            'weekly_time_off.*.start' => 'required|date_format:H:i',
            'weekly_time_off.*.end' => 'required|date_format:H:i',
        ]);

        $weeklySchedule = $this->validatedWeeklySchedule($request);

        $userData = $request->only(['name', 'email', 'password', 'phone']);
        $userData['password'] = Hash::make($userData['password']);
        $userData['role'] = 'barber';
        $userData['is_active'] = true;

        $barberData = $request->only(['bio', 'specialty']);
        $barberData['weekly_schedule'] = $weeklySchedule;
        $barberData['booking_enabled'] = (bool) $request->boolean('booking_enabled', true);
        $barberData['weekly_time_off'] = ! empty($validated['weekly_time_off'] ?? null)
            ? $validated['weekly_time_off']
            : null;

        return DB::transaction(function () use ($userData, $barberData, $validated) {
            $user = User::create($userData);
            $barber = Barber::create(array_merge($barberData, ['user_id' => $user->id]));
            $barber->services()->attach($validated['service_ids']);

            $barber->load(['user', 'services']);
            return response()->json($barber, 201);
        });
    }

    public function update(Request $request, int $id)
    {
        $barber = Barber::with('user')->findOrFail($id);

        if ($request->has('is_active') && ! $request->has('name')) {
            $validated = $request->validate(['is_active' => 'required|boolean']);
            $barber->user->update(['is_active' => $validated['is_active']]);
            $barber->load(['user', 'services']);
            return response()->json($barber);
        }

        $validated = $request->validate([
            'name' => 'required|string|max:100',
            'email' => 'required|email|unique:users,email,' . $barber->user_id,
            'password' => 'nullable|string|min:6',
            'phone' => 'nullable|string|max:20',
            'bio' => 'nullable|string',
            'specialty' => 'nullable|string|max:100',
            'service_ids' => 'required|array',
            'service_ids.*' => 'exists:services,id',
            'is_active' => 'boolean',
            'booking_enabled' => 'sometimes|boolean',
            'weekly_time_off' => 'nullable|array',
            'weekly_time_off.*.weekday' => 'required|integer|between:0,6',
            'weekly_time_off.*.start' => 'required|date_format:H:i',
            'weekly_time_off.*.end' => 'required|date_format:H:i',
        ]);

        $weeklySchedule = $this->validatedWeeklySchedule($request);

        return DB::transaction(function () use ($barber, $validated, $weeklySchedule) {
            $userData = [
                'name' => $validated['name'],
                'email' => $validated['email'],
                'phone' => $validated['phone'] ?? null,
            ];
            if (! empty($validated['password'])) {
                $userData['password'] = Hash::make($validated['password']);
            }
            if (isset($validated['is_active'])) {
                $userData['is_active'] = $validated['is_active'];
            }
            $barber->user->update($userData);

            $barberData = [
                'bio' => $validated['bio'] ?? null,
                'specialty' => $validated['specialty'] ?? null,
                'weekly_schedule' => $weeklySchedule,
                'booking_enabled' => array_key_exists('booking_enabled', $validated)
                    ? (bool) $validated['booking_enabled']
                    : $barber->booking_enabled,
                'weekly_time_off' => array_key_exists('weekly_time_off', $validated)
                    ? ($validated['weekly_time_off'] ?: null)
                    : $barber->weekly_time_off,
            ];
            $barber->update($barberData);
            $barber->services()->sync($validated['service_ids']);

            $barber->load(['user', 'services']);
            return response()->json($barber);
        });
    }

    /**
     * @return list<array{weekday:int,enabled:bool,start:string,end:string}>
     */
    private function validatedWeeklySchedule(Request $request): array
    {
        $rows = $request->input('weekly_schedule');
        if (! is_array($rows) || count($rows) !== 7) {
            throw ValidationException::withMessages([
                'weekly_schedule' => 'Debés enviar los 7 días de la semana (domingo = 0 … sábado = 6).',
            ]);
        }

        $validatedRows = [];
        foreach ($rows as $i => $row) {
            if (! is_array($row)) {
                throw ValidationException::withMessages([
                    "weekly_schedule.$i" => 'Cada día debe ser un objeto.',
                ]);
            }
            $weekday = isset($row['weekday']) ? (int) $row['weekday'] : -1;
            if ($weekday < 0 || $weekday > 6) {
                throw ValidationException::withMessages([
                    "weekly_schedule.$i.weekday" => 'weekday debe ser 0–6.',
                ]);
            }
            $enabled = filter_var($row['enabled'] ?? false, FILTER_VALIDATE_BOOLEAN);
            $start = isset($row['start']) ? (string) $row['start'] : '';
            $end = isset($row['end']) ? (string) $row['end'] : '';

            if ($enabled) {
                if (! preg_match('/^\d{2}:\d{2}$/', $start) || ! preg_match('/^\d{2}:\d{2}$/', $end)) {
                    throw ValidationException::withMessages([
                        "weekly_schedule.$i" => 'Horario inválido (usá HH:MM).',
                    ]);
                }
                if ($end <= $start) {
                    throw ValidationException::withMessages([
                        "weekly_schedule.$i" => 'La hora de fin debe ser mayor que la de inicio.',
                    ]);
                }
            }

            $validatedRows[] = [
                'weekday' => $weekday,
                'enabled' => $enabled,
                'start' => $enabled ? $start : '09:00',
                'end' => $enabled ? $end : '17:00',
            ];
        }

        $sorted = collect($validatedRows)->sortBy('weekday')->values()->all();
        $weekdays = array_column($sorted, 'weekday');
        if (count(array_unique($weekdays)) !== 7 || $weekdays !== range(0, 6)) {
            throw ValidationException::withMessages([
                'weekly_schedule' => 'Debe haber exactamente un bloque por cada día 0–6 (sin duplicar).',
            ]);
        }

        return $sorted;
    }

    public function destroy(int $id)
    {
        $barber = Barber::findOrFail($id);
        $barber->user->update(['is_active' => false]);
        return response()->json(['message' => 'Barber deactivated']);
    }
}
