<?php

declare(strict_types=1);

namespace App\Service\ApiResourceBuilder\Dolibarr;

use App\ApiResources\Dolibarr\DolibarrAccount;
use App\ApiResources\Dolibarr\DolibarrBill;
use App\ApiResources\Dolibarr\DolibarrContract;
use App\ApiResources\Dolibarr\DolibarrContractLine;
use App\ApiResources\Dolibarr\DolibarrOrder;
use App\Service\Dolibarr\DolibarrApiService;

class DolibarrAccountBuilder
{
    public const PRODUCT_MAPPING = [
        'Opentalent Artist' => 'PRODUCT_ARTIST',   // OT Artist
        'Opentalent Artist Premium' => 'PRODUCT_ARTIST_PREMIUM',   // OT Artist Premium
        'Opentalent Artist Premium (Essai)' => 'PRODUCT_ARTIST_PREMIUM_TRIAL',   // OT Artist Premium (trial)
        'Opentalent School' => 'PRODUCT_SCHOOL',   // OT School Standard
        'Opentalent School Premium' => 'PRODUCT_SCHOOL_PREMIUM',   // OT School Premium
        'Opentalent Manager' => 'PRODUCT_MANAGER',   // OT Manager
    ];

    public function __construct(
        private DolibarrApiService $dolibarrApiService,
    ) {
    }

    public function getDolibarrAccount(int $id): DolibarrAccount
    {
        // Get dolibarr account (society)
        $accountData = $this->dolibarrApiService->getSociety($id);
        $dolibarrAccount = $this->createDolibarrAccount($id, $accountData);

        if ($dolibarrAccount->getSocId() === null) {
            return $dolibarrAccount;
        }

        // Get active contract and services
        $contractData = $this->dolibarrApiService->getActiveContract($dolibarrAccount->getSocId());

        if ($contractData !== null) {
            $contract = $this->createDolibarrContract($contractData);
            $dolibarrAccount->setContract($contract);
        }

        // get last order (if any)
        $lastOrderData = $this->dolibarrApiService->getLastOrder($dolibarrAccount->getSocId());
        if ($lastOrderData !== null) {
            $order = $this->createDolibarrOrder($lastOrderData);
            $dolibarrAccount->setOrder($order);
        }

        // get bills
        $billsData = $this->dolibarrApiService->getBills($dolibarrAccount->getSocId());
        foreach ($billsData as $billData) {
            $bill = $this->createDolibarrBill($billData);
            $dolibarrAccount->addBill($bill);
        }

        return $dolibarrAccount;
    }

    /**
     * @param array<mixed>|null $accountData
     */
    public function createDolibarrAccount(int $organizationId, ?array $accountData): DolibarrAccount
    {
        $dolibarrAccount = new DolibarrAccount();
        $dolibarrAccount->setOrganizationId($organizationId);
        if ($accountData === null) {
            return $dolibarrAccount;
        }

        $dolibarrAccount->setSocId((int) $accountData['id'])
                        ->setClientNumber($accountData['code_client']);
        if (
            array_key_exists('options_2iopen_software_opentalent', $accountData['array_options'])
            && !empty($accountData['array_options']['options_2iopen_software_opentalent'])
        ) {
            $dolibarrAccount->setProduct(
                self::PRODUCT_MAPPING[$accountData['array_options']['options_2iopen_software_opentalent']]
            );
        }

        return $dolibarrAccount;
    }

    /**
     * @param array<mixed> $contractData
     */
    public function createDolibarrContract(array $contractData): DolibarrContract
    {
        $contract = new DolibarrContract();
        $contract->setRef($contractData['ref'] ?? '')
                 ->setSocId((int) $contractData['socid']);

        foreach ($contractData['lines'] as $lineData) {
            $line = $this->createDolibarrContractLine($lineData);
            $contract->addLine($line);
        }

        return $contract;
    }

    /**
     * @param array<mixed> $lineData
     *
     * @throws \Exception
     */
    public function createDolibarrContractLine(array $lineData): DolibarrContractLine
    {
        $line = new DolibarrContractLine();

        return $line->setId((int) $lineData['id'])
                    ->setContractId((int) $lineData['fk_contrat'])
                    ->setServiceRef($lineData['product_ref'])
                    ->setServiceLabel($lineData['product_label'])
                    ->setDateStart(new \DateTime(date('c', (int) $lineData['date_start'])))
                    ->setDateEnd(new \DateTime(date('c', (int) $lineData['date_end'])));
    }

    /**
     * @param array<mixed> $orderData
     *
     * @throws \Exception
     */
    public function createDolibarrOrder(array $orderData): DolibarrOrder
    {
        $order = new DolibarrOrder();

        return $order->setId((int) $orderData['id'])
                    ->setRef($orderData['ref'])
                    ->setDate(new \DateTime(date('c', (int) $orderData['date_validation'])));
    }

    /**
     * @param array<mixed> $billData
     *
     * @throws \Exception
     */
    public function createDolibarrBill(array $billData): DolibarrBill
    {
        $bill = new DolibarrBill();

        return $bill->setId((int) $billData['id'])
                    ->setRef($billData['ref'])
                    ->setTaxExcludedAmount((float) $billData['total_ht'])
                    ->setTaxIncludedAmount((float) $billData['total_ttc'])
                    ->setDate(new \DateTime(date('c', (int) $billData['date'])))
                    ->setPaid((bool) $billData['paye']);
    }
}
