<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Resources\TeamMemberResource;
use App\Models\TeamMember;
use App\Services\TeamMemberService;
use App\Services\UtilizationService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;

/**
 * @group Team Members
 *
 * Endpoints for managing team members.
 */
class TeamMemberController extends Controller
{
    /**
     * Team Member Service instance
     */
    protected TeamMemberService $teamMemberService;

    /**
     * Utilization Service instance
     */
    protected UtilizationService $utilizationService;

    /**
     * Constructor
     */
    public function __construct(TeamMemberService $teamMemberService, UtilizationService $utilizationService)
    {
        $this->teamMemberService = $teamMemberService;
        $this->utilizationService = $utilizationService;
    }

    /**
     * List all team members
     *
     * Get a list of all team members with optional filtering by active status.
     *
     * @authenticated
     *
     * @queryParam active boolean Filter by active status. Example: true
     *
     * @response 200 {
     *   "data": [
     *     {
     *       "id": "550e8400-e29b-41d4-a716-446655440000",
     *       "name": "John Doe",
     *       "role": {
     *         "id": 1,
     *         "name": "Backend Developer"
     *       },
     *       "hourly_rate": "150.00",
     *       "active": true,
     *       "created_at": "2024-01-15T10:00:00.000000Z",
     *       "updated_at": "2024-01-15T10:00:00.000000Z"
     *     }
     *   ]
     * }
     */
    public function index(Request $request): JsonResponse
    {
        $active = $request->has('active')
            ? filter_var($request->query('active'), FILTER_VALIDATE_BOOLEAN)
            : null;

        $teamMembers = $this->teamMemberService->getAll($active);

        return $this->wrapResource(TeamMemberResource::collection($teamMembers));
    }

    /**
     * Create a new team member
     *
     * Create a new team member with name, role, and hourly rate.
     *
     * @authenticated
     *
     * @bodyParam name string required Team member name. Example: John Doe
     * @bodyParam role_id integer required Role ID. Example: 1
     * @bodyParam hourly_rate numeric required Hourly rate (must be > 0). Example: 150.00
     * @bodyParam active boolean Active status (defaults to true). Example: true
     *
     * @response 201 {
     *   "data": {
     *     "id": "550e8400-e29b-41d4-a716-446655440000",
     *     "name": "John Doe",
     *     "role": {
     *       "id": 1,
     *       "name": "Backend Developer"
     *     },
     *     "hourly_rate": "150.00",
     *     "active": true,
     *     "created_at": "2024-01-15T10:00:00.000000Z",
     *     "updated_at": "2024-01-15T10:00:00.000000Z"
     *   }
     * }
     * @response 422 {"message":"Validation failed","errors":{"name":["The name field is required."],"hourly_rate":["Hourly rate must be greater than 0"]}}
     */
    public function store(Request $request): JsonResponse
    {
        try {
            $teamMember = $this->teamMemberService->create($request->all());

            return $this->wrapResource(new TeamMemberResource($teamMember), 201);
        } catch (ValidationException $e) {
            return response()->json([
                'message' => 'Validation failed',
                'errors' => $e->validator->errors(),
            ], 422);
        }
    }

    /**
     * Get a single team member
     *
     * Get details of a specific team member by ID.
     *
     * @authenticated
     *
     * @urlParam id string required Team member UUID. Example: 550e8400-e29b-41d4-a716-446655440000
     * @queryParam include_utilization boolean Include utilization data. Example: true
     * @queryParam month string Month for utilization calculation (Y-m format). Required if include_utilization is true. Example: 2026-02
     *
     * @response 200 {
     *   "data": {
     *     "id": "550e8400-e29b-41d4-a716-446655440000",
     *     "name": "John Doe",
     *     "role": {
     *       "id": 1,
     *       "name": "Backend Developer"
     *     },
     *     "hourly_rate": "150.00",
     *     "active": true,
     *     "created_at": "2024-01-15T10:00:00.000000Z",
     *     "updated_at": "2024-01-15T10:00:00.000000Z"
     *   }
     * }
     * @response 404 {"message":"Team member not found"}
     */
    public function show(Request $request, string $id): JsonResponse
    {
        $teamMember = $this->teamMemberService->findById($id);

        if (! $teamMember) {
            return response()->json([
                'message' => 'Team member not found',
            ], 404);
        }

        $data = (new TeamMemberResource($teamMember))->toArray($request);

        // Include utilization data if requested
        if ($request->boolean('include_utilization') && $request->has('month')) {
            $month = $request->query('month');
            $data['utilization'] = $this->utilizationService->getUtilizationData($id, $month);
        }

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

    /**
     * Update a team member
     *
     * Update details of an existing team member.
     *
     * @authenticated
     *
     * @urlParam id string required Team member UUID. Example: 550e8400-e29b-41d4-a716-446655440000
     *
     * @bodyParam name string Team member name. Example: John Doe
     * @bodyParam role_id integer Role ID. Example: 1
     * @bodyParam hourly_rate numeric Hourly rate (must be > 0). Example: 175.00
     * @bodyParam active boolean Active status. Example: false
     *
     * @response 200 {
     *   "data": {
     *     "id": "550e8400-e29b-41d4-a716-446655440000",
     *     "name": "John Doe",
     *     "role": {
     *       "id": 1,
     *       "name": "Backend Developer"
     *     },
     *     "hourly_rate": "175.00",
     *     "active": false,
     *     "created_at": "2024-01-15T10:00:00.000000Z",
     *     "updated_at": "2024-01-15T11:00:00.000000Z"
     *   }
     * }
     * @response 404 {"message":"Team member not found"}
     * @response 422 {"message":"Validation failed","errors":{"hourly_rate":["Hourly rate must be greater than 0"]}}
     */
    public function update(Request $request, string $id): JsonResponse
    {
        $teamMember = TeamMember::find($id);

        if (! $teamMember) {
            return response()->json([
                'message' => 'Team member not found',
            ], 404);
        }

        try {
            $teamMember = $this->teamMemberService->update($teamMember, $request->only([
                'name', 'role_id', 'hourly_rate', 'active',
            ]));

            return $this->wrapResource(new TeamMemberResource($teamMember));
        } catch (ValidationException $e) {
            return response()->json([
                'message' => 'Validation failed',
                'errors' => $e->validator->errors(),
            ], 422);
        }
    }

    /**
     * Delete a team member
     *
     * Delete a team member. Cannot delete if member has allocations or actuals.
     *
     * @authenticated
     *
     * @urlParam id string required Team member UUID. Example: 550e8400-e29b-41d4-a716-446655440000
     *
     * @response 200 {"message":"Team member deleted successfully"}
     * @response 404 {"message":"Team member not found"}
     * @response 422 {"message":"Cannot delete team member with active allocations","suggestion":"Consider deactivating the team member instead"}
     * @response 422 {"message":"Cannot delete team member with historical data","suggestion":"Consider deactivating the team member instead"}
     */
    public function destroy(string $id): JsonResponse
    {
        $teamMember = TeamMember::find($id);

        if (! $teamMember) {
            return response()->json([
                'message' => 'Team member not found',
            ], 404);
        }

        try {
            $this->teamMemberService->delete($teamMember);

            return response()->json([
                'message' => 'Team member deleted successfully',
            ]);
        } catch (\RuntimeException $e) {
            return response()->json([
                'message' => $e->getMessage(),
                'suggestion' => 'Consider deactivating the team member instead',
            ], 422);
        }
    }
}
