<?php

declare(strict_types=1);

namespace App\Entity;

use App\Enum\ContractNature;
use App\Repository\EmployeeContractPeriodRepository;
use DateTimeImmutable;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: EmployeeContractPeriodRepository::class)]
#[ORM\Table(name: 'employee_contract_periods')]
#[ORM\Index(columns: ['employee_id', 'start_date'], name: 'idx_emp_contract_period_employee_start')]
#[ORM\Index(columns: ['employee_id', 'end_date'], name: 'idx_emp_contract_period_employee_end')]
class EmployeeContractPeriod
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(type: 'integer')]
    private ?int $id = null;

    #[ORM\ManyToOne(targetEntity: Employee::class, inversedBy: 'contractPeriods')]
    #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
    private ?Employee $employee = null;

    #[ORM\ManyToOne(targetEntity: Contract::class)]
    #[ORM\JoinColumn(nullable: false)]
    private ?Contract $contract = null;

    #[ORM\Column(type: 'date_immutable')]
    private DateTimeImmutable $startDate;

    #[ORM\Column(type: 'date_immutable', nullable: true)]
    private ?DateTimeImmutable $endDate = null;

    #[ORM\Column(type: 'string', length: 20, options: ['default' => ContractNature::CDI->value])]
    private string $contractNature = ContractNature::CDI->value;

    #[ORM\Column(type: 'boolean', options: ['default' => false])]
    private bool $isDriver = false;

    #[ORM\Column(type: 'boolean', options: ['default' => false])]
    private bool $paidLeaveSettled = false;

    /**
     * Map ISO weekday (1=Mon..5=Fri) → minutes worked that day.
     * Required for non-standard TIME contracts (weeklyHours ∉ {35, 39}, non-INTERIM)
     * so that férié credit and absence credit respect the actual schedule.
     *
     * @var null|array<int, int>
     */
    #[ORM\Column(type: 'json', nullable: true)]
    private ?array $workDaysHours = null;

    #[ORM\ManyToOne(targetEntity: InterimAgency::class)]
    #[ORM\JoinColumn(nullable: true)]
    private ?InterimAgency $interimAgency = null;

    #[ORM\Column(type: 'text', nullable: true)]
    private ?string $comment = null;

    /**
     * @var Collection<int, ContractSuspension>
     */
    #[ORM\OneToMany(mappedBy: 'contractPeriod', targetEntity: ContractSuspension::class, cascade: ['persist', 'remove'])]
    private Collection $suspensions;

    #[ORM\Column(type: 'datetime_immutable')]
    private DateTimeImmutable $createdAt;

    public function __construct()
    {
        $this->createdAt   = new DateTimeImmutable();
        $this->startDate   = new DateTimeImmutable('today');
        $this->suspensions = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getEmployee(): ?Employee
    {
        return $this->employee;
    }

    public function setEmployee(?Employee $employee): self
    {
        $this->employee = $employee;

        return $this;
    }

    public function getContract(): ?Contract
    {
        return $this->contract;
    }

    public function setContract(?Contract $contract): self
    {
        $this->contract = $contract;

        return $this;
    }

    public function getStartDate(): DateTimeImmutable
    {
        return $this->startDate;
    }

    public function setStartDate(DateTimeImmutable $startDate): self
    {
        $this->startDate = $startDate;

        return $this;
    }

    public function getEndDate(): ?DateTimeImmutable
    {
        return $this->endDate;
    }

    public function setEndDate(?DateTimeImmutable $endDate): self
    {
        $this->endDate = $endDate;

        return $this;
    }

    public function getContractNature(): string
    {
        return $this->contractNature;
    }

    public function getContractNatureEnum(): ContractNature
    {
        return ContractNature::tryFrom($this->contractNature) ?? ContractNature::CDI;
    }

    public function setContractNature(ContractNature|string $contractNature): self
    {
        $value                = $contractNature instanceof ContractNature ? $contractNature->value : $contractNature;
        $this->contractNature = ContractNature::tryFrom($value)?->value ?? ContractNature::CDI->value;

        return $this;
    }

    public function getCreatedAt(): DateTimeImmutable
    {
        return $this->createdAt;
    }

    public function getIsDriver(): bool
    {
        return $this->isDriver;
    }

    public function setIsDriver(bool $isDriver): self
    {
        $this->isDriver = $isDriver;

        return $this;
    }

    public function isPaidLeaveSettled(): bool
    {
        return $this->paidLeaveSettled;
    }

    public function setPaidLeaveSettled(bool $paidLeaveSettled): self
    {
        $this->paidLeaveSettled = $paidLeaveSettled;

        return $this;
    }

    public function getComment(): ?string
    {
        return $this->comment;
    }

    public function setComment(?string $comment): self
    {
        $this->comment = $comment;

        return $this;
    }

    /**
     * @return null|array<int, int>
     */
    public function getWorkDaysHours(): ?array
    {
        return $this->workDaysHours;
    }

    /**
     * @param null|array<int, int> $workDaysHours
     */
    public function setWorkDaysHours(?array $workDaysHours): self
    {
        $this->workDaysHours = $workDaysHours;

        return $this;
    }

    public function getInterimAgency(): ?InterimAgency
    {
        return $this->interimAgency;
    }

    public function setInterimAgency(?InterimAgency $interimAgency): self
    {
        $this->interimAgency = $interimAgency;

        return $this;
    }

    /**
     * @return Collection<int, ContractSuspension>
     */
    public function getSuspensions(): Collection
    {
        return $this->suspensions;
    }
}
