<?php

namespace App\Services;

use App\Models\Project;
use App\Models\User;
use App\Models\ExpectedContribution;
use App\Models\ManagementYear;
use Carbon\Carbon;

class ExpectedContributionService
{
    /**
     * Génère les cotisations attendues pour un projet et un membre
     * en fonction de la fréquence, date de début et date de fin
     */
    public function generateExpectedContributions(Project $project, User $user, Carbon|string|null $joinedAt = null): void
    {
        // Date de début : Toujours la date de début du projet pour calculer les dettes depuis l'origine (règle métier)
        $startDate = Carbon::parse($project->start_date);

        // Date de fin : date de fin du projet ou null (indéfini)
        $endDate = $project->end_date ? Carbon::parse($project->end_date) : null;

        // Si pas de date de fin, générer jusqu'à 2 ans dans le futur par défaut
        // ou jusqu'à aujourd'hui si le projet a commencé dans le passé
        if (!$endDate) {
            $endDate = Carbon::now()->addYears(2);
        }

        // S'assurer que la date de fin est après la date de début
        if ($endDate->lessThanOrEqualTo($startDate)) {
            return;
        }

        // Montant de la cotisation
        $amount = $project->amount;

        // Générer les dates selon la fréquence
        $dueDates = $this->calculateDueDates($startDate, $endDate, $project->frequency, $project->custom_frequency_days);

        // Créer les cotisations attendues
        foreach ($dueDates as $dueDate) {
            // Vérifier si une cotisation attendue existe déjà pour cette date
            $existing = ExpectedContribution::where('project_id', $project->id)
                ->where('user_id', $user->id)
                ->where('due_date', $dueDate->format('Y-m-d'))
                ->first();

            if (!$existing) {
                // Trouver l'année de gestion correspondante
                $managementYear = ManagementYear::getForDate($dueDate);

                ExpectedContribution::create([
                    'project_id' => $project->id,
                    'user_id' => $user->id,
                    'management_year_id' => $managementYear ? $managementYear->id : null,
                    'amount' => $amount,
                    'due_date' => $dueDate,
                    'status' => $dueDate->isPast() ? 'en_retard' : 'attendu',
                ]);
            }
        }
    }

    /**
     * Calcule les dates d'échéance selon la fréquence
     */
    private function calculateDueDates(Carbon $startDate, Carbon $endDate, string $frequency, ?int $customDays = null): array
    {
        $dueDates = [];
        $currentDate = $startDate->copy();

        while ($currentDate->lessThanOrEqualTo($endDate)) {
            $dueDates[] = $currentDate->copy();

            // Calculer la prochaine date selon la fréquence
            switch ($frequency) {
                case 'mensuelle':
                    $currentDate->addMonth();
                    break;

                case 'hebdomadaire':
                    $currentDate->addWeek();
                    break;

                case 'annuelle':
                    $currentDate->addYear();
                    break;

                case 'personnalisee':
                    if ($customDays && $customDays > 0) {
                        $currentDate->addDays($customDays);
                    } else {
                        $currentDate->addMonth(); // Par défaut mensuel
                    }
                    break;

                default:
                    $currentDate->addMonth(); // Par défaut mensuel
                    break;
            }
        }

        return $dueDates;
    }

    /**
     * Régénère toutes les cotisations attendues pour un projet
     * Utile quand on modifie la fréquence ou les dates du projet
     */
    public function regenerateForProject(Project $project): void
    {
        // Supprimer les cotisations attendues non payées
        ExpectedContribution::where('project_id', $project->id)
            ->where('status', '!=', 'paye')
            ->delete();

        // Régénérer pour tous les membres
        foreach ($project->members as $member) {
            $joinedAt = $member->pivot->joined_at ?? $project->start_date;
            $this->generateExpectedContributions($project, $member, $joinedAt);
        }
    }

    /**
     * Génère les cotisations attendues pour tous les membres d'un projet
     */
    public function generateForAllMembers(Project $project): void
    {
        foreach ($project->members as $member) {
            $joinedAt = $member->pivot->joined_at ?? $project->start_date;
            $this->generateExpectedContributions($project, $member, $joinedAt);
        }
    }
}

