<?php

namespace App\Http\Controllers;

use App\Http\Resources\TeamResource;
use App\Models\Activity;
use App\Models\Member;
use App\Models\Season;
use App\Models\Team;
use App\Models\TeamWeekBonus;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;

class TeamController extends Controller
{
    public function index(): JsonResponse
    {
        $teams = Team::with(['members', 'captain', 'oneTimeCompletions', 'weekBonuses'])
            ->orderBy('id')
            ->get();

        return response()->json(['data' => TeamResource::collection($teams)]);
    }

    public function show(Team $team): JsonResponse
    {
        return response()->json(['data' => new TeamResource($team)]);
    }

    public function store(Request $request): JsonResponse
    {
        $season = Season::active() ?? Season::firstOrCreate(['is_active' => true], ['name' => 'Season']);

        $data = $request->validate([
            'name' => ['required', 'string', 'max:120', Rule::unique('teams')->where('season_id', $season->id)],
            'crest.shape' => ['nullable', 'in:shield,round,diamond,hex'],
            'crest.motif' => ['nullable', 'string', 'max:30'],
            'crest.primary' => ['nullable', 'regex:/^#[0-9a-fA-F]{6}$/'],
            'crest.secondary' => ['nullable', 'regex:/^#[0-9a-fA-F]{6}$/'],
            'crest.initials' => ['nullable', 'string', 'max:2'],
        ]);

        $crest = $data['crest'] ?? [];

        $team = Team::create([
            'season_id' => $season->id,
            'slug' => Str::slug($data['name']).'-'.Str::random(4),
            'name' => $data['name'],
            'crest_shape' => $crest['shape'] ?? 'shield',
            'crest_motif' => $crest['motif'] ?? 'star',
            'crest_primary' => $crest['primary'] ?? '#b21e2e',
            'crest_secondary' => $crest['secondary'] ?? '#0e0e10',
            'crest_initials' => strtoupper($crest['initials'] ?? substr($data['name'], 0, 2)),
        ]);

        return response()->json(['data' => new TeamResource($team)], 201);
    }

    public function update(Request $request, Team $team): JsonResponse
    {
        $data = $request->validate([
            'name' => ['sometimes', 'string', 'max:120', Rule::unique('teams')->where('season_id', $team->season_id)->ignore($team->id)],
            'captain_id' => ['sometimes', 'nullable', 'integer', Rule::exists('members', 'id')->where('team_id', $team->id)],
            'crest_mode' => ['sometimes', 'in:crest,logo'],
            'crest' => ['sometimes', 'array'],
            'crest.shape' => ['sometimes', 'in:shield,round,diamond,hex'],
            'crest.motif' => ['sometimes', 'string', 'max:30'],
            'crest.primary' => ['sometimes', 'regex:/^#[0-9a-fA-F]{6}$/'],
            'crest.secondary' => ['sometimes', 'regex:/^#[0-9a-fA-F]{6}$/'],
            'crest.initials' => ['sometimes', 'string', 'max:2'],
        ]);

        if (array_key_exists('name', $data)) $team->name = $data['name'];
        if (array_key_exists('captain_id', $data)) $team->captain_id = $data['captain_id'];
        if (array_key_exists('crest_mode', $data)) $team->crest_mode = $data['crest_mode'];

        if (isset($data['crest'])) {
            $crest = $data['crest'];
            if (isset($crest['shape'])) $team->crest_shape = $crest['shape'];
            if (isset($crest['motif'])) $team->crest_motif = $crest['motif'];
            if (isset($crest['primary'])) $team->crest_primary = $crest['primary'];
            if (isset($crest['secondary'])) $team->crest_secondary = $crest['secondary'];
            if (isset($crest['initials'])) $team->crest_initials = strtoupper($crest['initials']);
        }

        $team->save();

        return response()->json(['data' => new TeamResource($team->fresh(['members', 'captain', 'oneTimeCompletions', 'weekBonuses']))]);
    }

    public function destroy(Team $team): JsonResponse
    {
        // Detach captain first to avoid FK conflict, then cascade members and the team itself.
        $team->captain_id = null;
        $team->save();
        $team->members()->delete();
        $team->delete();
        return response()->json(['message' => 'Deleted.']);
    }

    public function setCaptain(Request $request, Team $team): JsonResponse
    {
        $data = $request->validate([
            'member_id' => ['required', 'integer', Rule::exists('members', 'id')->where('team_id', $team->id)],
        ]);

        $team->captain_id = $data['member_id'];
        $team->save();

        return response()->json(['data' => new TeamResource($team->fresh(['members', 'captain', 'oneTimeCompletions', 'weekBonuses']))]);
    }

    public function uploadLogo(Request $request, Team $team): JsonResponse
    {
        $request->validate([
            'logo' => ['required', 'file', 'image', 'mimes:png,jpg,jpeg,webp,svg', 'max:2048'],
        ]);

        if ($team->logo_path) {
            Storage::disk('public')->delete($team->logo_path);
        }

        $path = $request->file('logo')->store('team-logos', 'public');
        $team->logo_path = $path;
        $team->crest_mode = 'logo';
        $team->save();

        return response()->json(['data' => new TeamResource($team->fresh(['members', 'captain', 'oneTimeCompletions', 'weekBonuses']))]);
    }

    public function deleteLogo(Team $team): JsonResponse
    {
        if ($team->logo_path) {
            Storage::disk('public')->delete($team->logo_path);
        }
        $team->logo_path = null;
        $team->crest_mode = 'crest';
        $team->save();

        return response()->json(['data' => new TeamResource($team->fresh(['members', 'captain', 'oneTimeCompletions', 'weekBonuses']))]);
    }

    public function toggleOneTime(Request $request, Team $team, string $activityKey): JsonResponse
    {
        $activity = Activity::where('key', $activityKey)->firstOrFail();

        if (! $activity->one_time || $activity->scope !== 'team') {
            return response()->json(['message' => 'Activity is not a team one-time activity.'], 422);
        }

        $data = $request->validate(['done' => ['required', 'boolean']]);

        if ($data['done']) {
            $team->oneTimeCompletions()->syncWithoutDetaching([$activity->id => ['completed_at' => now()]]);
        } else {
            $team->oneTimeCompletions()->detach($activity->id);
        }

        return response()->json(['data' => new TeamResource($team->fresh(['members', 'captain', 'oneTimeCompletions', 'weekBonuses']))]);
    }

    private function upsertWeekBonus(Team $team, string $weekId, string $field, int $points): JsonResponse
    {
        $bonus = TeamWeekBonus::firstOrNew(['team_id' => $team->id, 'week_id' => $weekId]);
        $bonus->{$field} = $points;
        $bonus->save();

        return response()->json(['data' => new TeamResource($team->fresh(['members', 'captain', 'oneTimeCompletions', 'weekBonuses']))]);
    }

    public function setMcmBonus(Request $request, Team $team, string $weekId): JsonResponse
    {
        $data = $request->validate([
            'points' => ['required', 'integer', 'in:0,50,100,200'],
        ]);
        return $this->upsertWeekBonus($team, $weekId, 'mcm_bonus', $data['points']);
    }

    public function setTyfcbBonus(Request $request, Team $team, string $weekId): JsonResponse
    {
        $data = $request->validate([
            'points' => ['required', 'integer', 'in:0,100,200,300'],
        ]);
        return $this->upsertWeekBonus($team, $weekId, 'tyfcb_bonus', $data['points']);
    }

    public function setAttendanceBonus(Request $request, Team $team, string $weekId): JsonResponse
    {
        $data = $request->validate([
            'points' => ['required', 'integer', 'in:0,50,100'],
        ]);
        return $this->upsertWeekBonus($team, $weekId, 'attendance_bonus', $data['points']);
    }
}
