<?php

namespace App\Services;

use App\Models\Allocation;
use App\Models\Project;
use App\Models\TeamMember;

class AllocationValidationService
{
    /**
     * Validate an allocation against team member capacity.
     *
     * @return array{valid: bool, warning: ?string, utilization: float}
     */
    public function validateCapacity(
        string $teamMemberId,
        string $month,
        float $newHours,
        ?string $excludeAllocationId = null
    ): array {
        $teamMember = TeamMember::with('role')->find($teamMemberId);

        if (! $teamMember) {
            return ['valid' => true, 'warning' => null, 'utilization' => 0];
        }

        // Get capacity for the month
        $capacityService = app(CapacityService::class);
        $capacityData = $capacityService->calculateIndividualCapacity($teamMemberId, $month);
        $capacity = $capacityData['hours'] ?? 0;

        if ($capacity <= 0) {
            return ['valid' => true, 'warning' => null, 'utilization' => 0];
        }

        // Convert YYYY-MM to YYYY-MM-01 for database query
        $monthDate = $month . '-01';

        // Get existing allocations for this team member in this month
        $existingHours = Allocation::where('team_member_id', $teamMemberId)
            ->where('month', $monthDate)
            ->when($excludeAllocationId, fn ($query) => $query->where('id', '!=', $excludeAllocationId))
            ->sum('allocated_hours');

        $totalHours = $existingHours + $newHours;
        $utilization = ($totalHours / $capacity) * 100;

        // Over-allocated: warn but allow
        if ($utilization > 100) {
            $overBy = $totalHours - $capacity;

            return [
                'valid' => true,
                'warning' => "Team member over-allocated by {$overBy} hours ({$utilization}% utilization)",
                'utilization' => round($utilization, 1),
            ];
        }

        return [
            'valid' => true,
            'warning' => null,
            'utilization' => round($utilization, 1),
        ];
    }

    /**
     * Validate an allocation against project approved estimate.
     *
     * @return array{valid: bool, indicator: string, message: ?string}
     */
    public function validateApprovedEstimate(
        string $projectId,
        string $month,
        float $newHours,
        ?string $excludeAllocationId = null
    ): array {
        $project = Project::find($projectId);

        if (! $project || ! $project->approved_estimate) {
            return ['valid' => true, 'indicator' => 'gray', 'message' => null];
        }

        // Convert YYYY-MM to YYYY-MM-01 for database query
        $monthDate = $month . '-01';

        // Get existing allocations for this project in this month
        $existingHours = Allocation::where('project_id', $projectId)
            ->where('month', $monthDate)
            ->when($excludeAllocationId, fn ($query) => $query->where('id', '!=', $excludeAllocationId))
            ->sum('allocated_hours');

        $totalHours = $existingHours + $newHours;
        $approved = (float) $project->approved_estimate;

        if ($approved <= 0) {
            return ['valid' => true, 'indicator' => 'gray', 'message' => null];
        }

        $percentage = ($totalHours / $approved) * 100;

        // Over-allocated: RED indicator
        if ($percentage > 100) {
            $overBy = $totalHours - $approved;

            return [
                'valid' => true,
                'indicator' => 'red',
                'message' => "{$percentage}% allocated (over by {$overBy} hours). Project will be over-charged.",
            ];
        }

        // Exactly at estimate: GREEN indicator
        if ($percentage >= 100) {
            return [
                'valid' => true,
                'indicator' => 'green',
                'message' => '100% allocated',
            ];
        }

        // Under-allocated: YELLOW indicator
        $underBy = $approved - $totalHours;

        return [
            'valid' => true,
            'indicator' => 'yellow',
            'message' => "{$percentage}% allocated (under by {$underBy} hours)",
        ];
    }

    /**
     * Get validation results for all allocations in a month.
     */
    public function getAllocationValidation(
        string $teamMemberId,
        string $month
    ): array {
        $capacityValidation = $this->validateCapacity($teamMemberId, $month, 0);

        // Convert YYYY-MM to YYYY-MM-01 for database query
        $monthDate = $month . '-01';

        $allocations = Allocation::where('team_member_id', $teamMemberId)
            ->where('month', $monthDate)
            ->with('project')
            ->get();

        $projectValidations = $allocations->map(function ($allocation) use ($month) {
            return $this->validateApprovedEstimate(
                $allocation->project_id,
                $month,
                (float) $allocation->allocated_hours,
                $allocation->id
            );
        });

        return [
            'capacity' => $capacityValidation,
            'projects' => $projectValidations,
        ];
    }
}
