<?php

namespace App\Http\Controllers\Cartograhie\ChartsData;

use App\Helpers\Normalizer\DateNormalizer;
use App\Http\Controllers\Cartograhie\Filters\FilterController;
use CARTOGRAPHIE;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class AllResultsForController
{
    /**
     * @var FilterController
     */
    private $filter;

    /**
     * Constructeur de la classe AllResultsForController.
     * Initialise le service de filtre.
     *
     * @param FilterController $filterController Le service de filtre à utiliser.
     */
    public function __construct(FilterController $filterController)
    {
        $this->filter = $filterController;
    }

    /**
     * Récupère tous les résultats pour le contrôleur.
     *
     * @return array Un tableau contenant tous les résultats.
     */
    public function getAllResultsFunctionInController(): array
    {
        $directionsAndServices = $this->returnDirectionsAndServicesAndDomain();
        $totalOfSuppliers = $this->retrieveSuppliersByDomain();
        $averageAmountSuppliersByDomain = $this->retrieveAverageAmountSuppliersByDomain();
        $activeMarkets = $this->retrieveActiveMarkets();
        $notifiedMarket = $this->retrieveNotifiedMarket();
        $filters = $this->filter->getFilters(request());
        $startDate = $filters['startDate'];
        $endDate = $filters['endDate'];

        if ($startDate) {
            $startDate = DateNormalizer::normalizeDate($startDate);
        }

        if ($endDate) {
            $endDate = DateNormalizer::normalizeDate($endDate);
        }

        return array_merge(
            ['directions' => $directionsAndServices['directions']],
            ['services' => $directionsAndServices['services']],
            ['domains' => $directionsAndServices['domains']],
            ['totalOfSuppliers' => $totalOfSuppliers],
            ['averageAmountSuppliersByDomain' => $averageAmountSuppliersByDomain],
            ['activeMarkets' => $activeMarkets],
            ['notifiedMarket' => $notifiedMarket],
            $this->filter->getRoleAndHeaderStatus(),
            ['startDate' => $startDate],
            ['endDate' => $endDate],
            ['domainSelected' => $filters['domainSelected']],
            ['directionSelected' => $filters['directionSelected']],
            ['serviceSelected' => $filters['serviceSelected']]
        );
    }

    /**
     * Retourne les directions, les services et les domaines.
     *
     * @return array Un tableau contenant les directions, les services et les domaines.
     */
    public function returnDirectionsAndServicesAndDomain(): array
    {
        $directions = $this->getDomaineStructureDirectionFromDBB(CARTOGRAPHIE::LIBELLE_DIRECTION);

        $services = $this->getDomaineStructureDirectionFromDBB(CARTOGRAPHIE::LIBELLE_SERVICE);

        $domains = $this->getDomaineStructureDirectionFromDBB(CARTOGRAPHIE::DOMAINE);

        return [
            'directions' => $directions,
            'services' => $services,
            'domains' => $domains,
        ];
    }

    /**
     * Récupère les domaines, les structures et les directions depuis la base de données.
     *
     * @param string $params Les paramètres à récupérer.
     *
     * @return array Les domaines, les structures et les directions.
     */
    public function getDomaineStructureDirectionFromDBB($params): array
    {
        return DB::table('csv_donnees_client')
            ->select($params)
            ->where(CARTOGRAPHIE::STRUCTURE_ID, Auth::user()->structure_id)
            ->distinct()
            ->get()
            ->pluck($params)
            ->toArray();
    }

    /**
     * Récupère les fournisseurs par domaine.
     *
     * @return int Le nombre de fournisseurs par domaine.
     */
    public function retrieveSuppliersByDomain(): int
    {
        $query = DB::table('csv_donnees_client')
            ->where(CARTOGRAPHIE::STRUCTURE_ID, Auth::user()->structure_id);

        if ($this->filter->getFilters(request())) {
            $query = $this->filter->applyFilters($query, request());
        }

        return $query->distinct()->count(CARTOGRAPHIE::TIERS_NOM);
    }

    /**
     * Récupère le montant moyen des fournisseurs par domaine.
     *
     * @return mixed Le montant moyen des fournisseurs par domaine.
     */
    public function retrieveAverageAmountSuppliersByDomain()
    {
        $totalOfSuppliers = $this->retrieveSuppliersByDomain();

        $query = DB::table('csv_donnees_client')
            ->select(CARTOGRAPHIE::DOMAINE, DB::raw('SUM(`montant_ht`) as montant_ht'))
            ->where(CARTOGRAPHIE::STRUCTURE_ID, Auth::user()->structure_id);
        if ($this->filter->getFilters(request())) {
            $query = $this->filter->applyFilters($query, request());
        }
        $query = $query->groupBy(CARTOGRAPHIE::DOMAINE)->first();

        if ($query == null || $totalOfSuppliers == 0) {
            return 0;
        }
        $query->montant_ht = $query->montant_ht / $totalOfSuppliers;
        return $query;
    }

    /**
     * Récupère les marchés actifs.
     *
     * @return int|null Le nombre de marchés actifs, ou null si aucune date de fin ou domaine n'est sélectionné.
     */
    public function retrieveActiveMarkets(): ?int
    {
        if ($this->filter->getFilters(request())['endDate'] && $this->filter->getFilters(request())['domainSelected']) {
            $query = DB::table('csv_donnees_client')
                ->where(CARTOGRAPHIE::STRUCTURE_ID, Auth::user()->structure_id)
                ->where(CARTOGRAPHIE::LIBELLE_MARCHE, '!=', 'HORS MARCHE')
                ->where(CARTOGRAPHIE::DOMAINE, $this->filter->getFilters(request())['domainSelected'])
                ->where('date_fin', '>=', $this->filter->getFilters(request())['endDate']);

            if ($this->filter->GetFilters(request())['directionSelected']) {
                $query->where(CARTOGRAPHIE::LIBELLE_DIRECTION, $this->filter->GetFilters(request())['directionSelected']);
            }

            if ($this->filter->GetFilters(request())['serviceSelected']) {
                $query->where(CARTOGRAPHIE::LIBELLE_SERVICE, $this->filter->GetFilters(request())['serviceSelected']);
            }

            return $query->distinct()->count(CARTOGRAPHIE::LIBELLE_MARCHE);
        } else {
            return null;
        }
    }

    /**
     * Récupère le marché notifié.
     *
     * @return int|null Le nombre de marchés notifiés, ou null si aucune date de début ou domaine n'est sélectionné.
     */
    public function retrieveNotifiedMarket(): ?int
    {
        if ($this->filter->getFilters(request())['startDate'] && $this->filter->getFilters(request())['domainSelected']) {
            $query = DB::table('csv_donnees_client')
                ->where(CARTOGRAPHIE::STRUCTURE_ID, Auth::user()->structure_id)
                ->where('date_debut', '>=', $this->filter->getFilters(request())['startDate'])
                ->where(CARTOGRAPHIE::DOMAINE, $this->filter->getFilters(request())['domainSelected']);

            if ($this->filter->GetFilters(request())['directionSelected']) {
                $query->where(CARTOGRAPHIE::LIBELLE_DIRECTION, $this->filter->GetFilters(request())['directionSelected']);
            }

            if ($this->filter->GetFilters(request())['serviceSelected']) {
                $query->where(CARTOGRAPHIE::LIBELLE_SERVICE, $this->filter->GetFilters(request())['serviceSelected']);
            }


            return $query->distinct()->count(CARTOGRAPHIE::LIBELLE_MARCHE);
        } else {
            return null;
        }
    }
}
