<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Resources\CapacityResource;
use App\Http\Resources\RevenueResource;
use App\Http\Resources\TeamCapacityResource;
use App\Http\Resources\TeamMemberAvailabilityResource;
use App\Models\TeamMember;
use App\Services\CapacityService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class CapacityController extends Controller
{
    public function __construct(protected CapacityService $capacityService) {}

    /**
     * Get Individual Capacity
     *
     * Calculate capacity for a specific team member in a given month.
     *
     * @group Capacity Planning
     *
     * @urlParam month string required The month in YYYY-MM format. Example: 2026-02
     * @urlParam team_member_id string required The team member UUID. Example: 550e8400-e29b-41d4-a716-446655440000
     *
     * @response {
     *   "data": {
     *     "team_member_id": "550e8400-e29b-41d4-a716-446655440000",
     *     "month": "2026-02",
     *     "working_days": 20,
     *     "person_days": 18.5,
     *     "hours": 148,
     *     "details": [
     *       {
     *         "date": "2026-02-02",
     *         "availability": 1,
     *         "is_pto": false
     *       }
     *     ]
     *   }
     * }
     */
    public function individual(Request $request): JsonResponse
    {
        $data = $request->validate([
            'month' => 'required|date_format:Y-m',
            'team_member_id' => 'required|exists:team_members,id',
        ]);

        $capacity = $this->capacityService->calculateIndividualCapacity($data['team_member_id'], $data['month']);
        $workingDays = $this->capacityService->calculateWorkingDays($data['month']);

        $payload = [
            'team_member_id' => $data['team_member_id'],
            'month' => $data['month'],
            'working_days' => $workingDays,
            'person_days' => $capacity['person_days'],
            'hours' => $capacity['hours'],
            'details' => $capacity['details'],
        ];

        return $this->wrapResource(new CapacityResource($payload));
    }

    /**
     * Get Team Capacity
     *
     * Summarize the combined capacity for all active team members in a month.
     *
     * @group Capacity Planning
     *
     * @urlParam month string required The month in YYYY-MM format. Example: 2026-02
     *
     * @response {
     *   "data": {
     *     "month": "2026-02",
     *     "total_person_days": 180.5,
     *     "total_hours": 1444,
     *     "members": [
     *       {
     *         "id": "550e8400-e29b-41d4-a716-446655440000",
     *         "name": "Ada Lovelace",
     *         "person_days": 18.5,
     *         "hours": 148
     *       }
     *     ]
     *   }
     * }
     */
    public function team(Request $request): JsonResponse
    {
        $data = $request->validate([
            'month' => 'required|date_format:Y-m',
        ]);

        $payload = $this->capacityService->calculateTeamCapacity($data['month']);

        return $this->wrapResource(new TeamCapacityResource($payload));
    }

    /**
     * Get Possible Revenue
     *
     * Estimate monthly revenue based on capacity hours and hourly rates.
     *
     * @group Capacity Planning
     *
     * @urlParam month string required The month in YYYY-MM format. Example: 2026-02
     *
     * @response {
     *   "data": {
     *     "month": "2026-02",
     *     "possible_revenue": 21500.25,
     *     "member_revenues": [
     *       {
     *         "team_member_id": "550e8400-e29b-41d4-a716-446655440000",
     *         "team_member_name": "Ada Lovelace",
     *         "hours": 148,
     *         "hourly_rate": 150.0,
     *         "revenue": 22200.0
     *       }
     *     ]
     *   }
     * }
     */
    public function revenue(Request $request): JsonResponse
    {
        $data = $request->validate([
            'month' => 'required|date_format:Y-m',
        ]);

        $revenue = $this->capacityService->calculatePossibleRevenue($data['month']);
        $memberRevenues = [];

        TeamMember::where('active', true)
            ->get()
            ->each(function (TeamMember $member) use ($data, &$memberRevenues): void {
                $capacity = $this->capacityService->calculateIndividualCapacity($member->id, $data['month']);
                $hours = $capacity['hours'];
                $hourlyRate = $member->hourly_rate !== null ? (float) $member->hourly_rate : null;
                $memberRevenue = $hourlyRate !== null ? round($hours * $hourlyRate, 2) : 0.0;

                $memberRevenues[] = [
                    'team_member_id' => $member->id,
                    'team_member_name' => $member->name,
                    'hours' => $hours,
                    'hourly_rate' => $hourlyRate,
                    'revenue' => $memberRevenue,
                ];
            });

        return $this->wrapResource(new RevenueResource([
            'month' => $data['month'],
            'possible_revenue' => $revenue,
            'member_revenues' => $memberRevenues,
        ]));
    }

    /**
     * Save Team Member Availability
     *
     * Persist a daily availability override and refresh cached capacity totals.
     *
     * @group Capacity Planning
     *
     * @bodyParam team_member_id string required The team member UUID.
     * @bodyParam date string required The date for the availability override (YYYY-MM-DD).
     * @bodyParam availability numeric required The availability value (0, 0.5, 1.0).
     *
     * @response 201 {
     *   "data": {
     *     "team_member_id": "550e8400-e29b-41d4-a716-446655440000",
     *     "date": "2026-02-03",
     *     "availability": 0.5
     *   }
     * }
     */
    public function saveAvailability(Request $request): JsonResponse
    {
        $data = $request->validate([
            'team_member_id' => 'required|exists:team_members,id',
            'date' => 'required|date_format:Y-m-d',
            'availability' => ['required', 'numeric', Rule::in([0, 0.5, 1])],
        ]);

        $entry = $this->capacityService->upsertTeamMemberAvailability(
            $data['team_member_id'],
            $data['date'],
            (float) $data['availability']
        );

        return $this->wrapResource(new TeamMemberAvailabilityResource($entry), 201);
    }

    /**
     * Batch Update Team Member Availability
     *
     * Persist multiple daily availability overrides in a single batch operation.
     *
     * @group Capacity Planning
     *
     * @bodyParam month string required The month in YYYY-MM format. Example: 2026-02
     * @bodyParam updates array required Array of availability updates.
     * @bodyParam updates[].team_member_id string required The team member UUID.
     * @bodyParam updates[].date string required The date (YYYY-MM-DD).
     * @bodyParam updates[].availability numeric required The availability value (0, 0.5, 1).
     *
     * @response {
     *   "data": {
     *     "saved": 12,
     *     "month": "2026-02"
     *   }
     * }
     */
    public function batchUpdateAvailability(Request $request): JsonResponse
    {
        $data = $request->validate([
            'month' => 'required|date_format:Y-m',
            'updates' => 'present|array',
            'updates.*.team_member_id' => 'required_with:updates|exists:team_members,id',
            'updates.*.date' => 'required_with:updates|date_format:Y-m-d',
            'updates.*.availability' => ['required_with:updates', 'numeric', Rule::in([0, 0.5, 1])],
        ]);

        $saved = $this->capacityService->batchUpsertAvailability(
            $data['updates'],
            $data['month']
        );

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