<?php

declare(strict_types=1);

namespace App\Dto\WorkHours;

final class DayContextRow
{
    public function __construct(
        public int $employeeId,
        public bool $hasContractAtDate = true,
        public ?string $absenceLabel = null,
        public ?string $absenceColor = null,
        public ?string $absenceHalf = null,
        public bool $absentMorning = false,
        public bool $absentAfternoon = false,
        public int $creditedMinutes = 0,
        public float $creditedPresenceUnits = 0.0,
        public bool $isDriverContract = false,
        public bool $hasFormation = false,
        public ?string $formationLabel = null,
        public int $virtualHolidayMinutes = 0,
        public ?string $contractNature = null,
        public ?string $trackingMode = null,
        public ?int $weeklyHours = null,
        public ?string $contractType = null,
        public ?string $contractName = null,
        /** @var null|array<int, int> iso day (1=Mon..5=Fri) → minutes, planning des jours travaillés (CUSTOM uniquement) */
        public ?array $workDaysHours = null,
    ) {}

    public function setFormation(string $label): void
    {
        $this->hasFormation   = true;
        $this->formationLabel = $label;
    }

    public function addAbsence(
        ?string $label,
        ?string $color,
        bool $morning,
        bool $afternoon,
        int $creditedMinutes,
        float $creditedPresenceUnits
    ): void {
        // Fusionne plusieurs absences du même jour sur la ligne salarié.
        $this->absentMorning   = $this->absentMorning   || $morning;
        $this->absentAfternoon = $this->absentAfternoon || $afternoon;

        // Garde un libellé lisible: unique si possible, sinon "Absences multiples".
        if (null === $this->absenceLabel) {
            $this->absenceLabel = $label;
        } elseif ($label !== $this->absenceLabel) {
            $this->absenceLabel = 'Absences multiples';
        }

        // Si plusieurs types d'absence différents sont fusionnés sur la même journée,
        // on retire la couleur métier spécifique.
        if (null === $this->absenceColor) {
            $this->absenceColor = $color;
        } elseif ($color !== $this->absenceColor) {
            $this->absenceColor = null;
        }

        // AM/PM seulement pour les demi-journées, null pour journée complète.
        $this->absenceHalf = $this->resolveHalfLabel($this->absentMorning, $this->absentAfternoon);
        // Cumule les minutes créditées par les absences "comptées comme travaillées".
        $this->creditedMinutes += $creditedMinutes;
        // Cumule les unités de présence créditées (0.5 par demi-journée).
        $this->creditedPresenceUnits += $creditedPresenceUnits;
    }

    /**
     * @return array{
     *     employeeId:int,
     *     hasContractAtDate:bool,
     *     absenceLabel:?string,
     *     absenceColor:?string,
     *     absenceHalf:?string,
     *     absentMorning:bool,
     *     absentAfternoon:bool,
     *     creditedMinutes:int,
     *     creditedPresenceUnits:float,
     *     isDriverContract:bool,
     *     hasFormation:bool,
     *     formationLabel:?string,
     *     virtualHolidayMinutes:int,
     *     contractNature:?string,
     *     trackingMode:?string,
     *     weeklyHours:?int,
     *     contractType:?string,
     *     contractName:?string,
     *     workDaysHours:?array<int, int>
     * }
     */
    public function toArray(): array
    {
        return [
            'employeeId'            => $this->employeeId,
            'hasContractAtDate'     => $this->hasContractAtDate,
            'absenceLabel'          => $this->absenceLabel,
            'absenceColor'          => $this->absenceColor,
            'absenceHalf'           => $this->absenceHalf,
            'absentMorning'         => $this->absentMorning,
            'absentAfternoon'       => $this->absentAfternoon,
            'creditedMinutes'       => $this->creditedMinutes,
            'creditedPresenceUnits' => $this->creditedPresenceUnits,
            'isDriverContract'      => $this->isDriverContract,
            'hasFormation'          => $this->hasFormation,
            'formationLabel'        => $this->formationLabel,
            'virtualHolidayMinutes' => $this->virtualHolidayMinutes,
            'contractNature'        => $this->contractNature,
            'trackingMode'          => $this->trackingMode,
            'weeklyHours'           => $this->weeklyHours,
            'contractType'          => $this->contractType,
            'contractName'          => $this->contractName,
            'workDaysHours'         => $this->workDaysHours,
        ];
    }

    private function resolveHalfLabel(bool $morning, bool $afternoon): ?string
    {
        // Matin + après-midi => journée complète, pas de libellé AM/PM.
        if ($morning && $afternoon) {
            return null;
        }
        if ($morning) {
            return 'AM';
        }
        if ($afternoon) {
            return 'PM';
        }

        return null;
    }
}
