<?php

declare(strict_types=1);

namespace App\Models;

use App\Core\Model;
use PDO;

final class Client extends Model
{
    public function allActive(): array
    {
        $sql = "
            SELECT c.*, t.libelle AS type_client
            FROM clients c
            LEFT JOIN types_clients t ON t.id = c.type_client_id
            WHERE c.actif = 1
            ORDER BY c.raison_sociale ASC
        ";

        return $this->db->query($sql)->fetchAll(PDO::FETCH_ASSOC);
    }

    public function find(int $id): ?array
    {
        $stmt = $this->db->prepare("SELECT * FROM clients WHERE id = :id LIMIT 1");
        $stmt->execute(['id' => $id]);
        $client = $stmt->fetch(PDO::FETCH_ASSOC);
        return $client ?: null;
    }



    public function findByCode(string $code): ?array
    {
        $stmt = $this->db->prepare("SELECT * FROM clients WHERE code_client = :code LIMIT 1");
        $stmt->execute(['code' => $code]);
        $client = $stmt->fetch(PDO::FETCH_ASSOC);
        return $client ?: null;
    }

    public function nextCode(): string
    {
        $stmt = $this->db->query("SELECT code_client FROM clients WHERE code_client LIKE 'CL%' ORDER BY id DESC LIMIT 1");
        $last = $stmt->fetchColumn();

        if (!$last) {
            return 'CL000001';
        }

        $number = (int) substr((string) $last, 2);
        return 'CL' . str_pad((string) ($number + 1), 6, '0', STR_PAD_LEFT);
    }

    public function create(array $data): int
    {
        $sql = "
            INSERT INTO clients (
                type_client_id, code_client, raison_sociale, contact, adresse, code_postal, ville, pays,
                telephone, mobile, email, site_web, ice, identifiant_fiscal, registre_commerce,
                commercial, remise, mode_reglement, delai_paiement, plafond_credit, observations
            ) VALUES (
                :type_client_id, :code_client, :raison_sociale, :contact, :adresse, :code_postal, :ville, :pays,
                :telephone, :mobile, :email, :site_web, :ice, :identifiant_fiscal, :registre_commerce,
                :commercial, :remise, :mode_reglement, :delai_paiement, :plafond_credit, :observations
            )
        ";

        $stmt = $this->db->prepare($sql);
        $stmt->execute($this->normalize($data));
        $id = (int) $this->db->lastInsertId();
        $this->log($id, 'creation', 'Création du client');
        return $id;
    }

    public function update(int $id, array $data): void
    {
        $sql = "
            UPDATE clients SET
                type_client_id = :type_client_id,
                code_client = :code_client,
                raison_sociale = :raison_sociale,
                contact = :contact,
                adresse = :adresse,
                code_postal = :code_postal,
                ville = :ville,
                pays = :pays,
                telephone = :telephone,
                mobile = :mobile,
                email = :email,
                site_web = :site_web,
                ice = :ice,
                identifiant_fiscal = :identifiant_fiscal,
                registre_commerce = :registre_commerce,
                commercial = :commercial,
                remise = :remise,
                mode_reglement = :mode_reglement,
                delai_paiement = :delai_paiement,
                plafond_credit = :plafond_credit,
                observations = :observations
            WHERE id = :id
        ";

        $params = $this->normalize($data);
        $params['id'] = $id;
        $stmt = $this->db->prepare($sql);
        $stmt->execute($params);
        $this->log($id, 'modification', 'Modification de la fiche client');
    }

    public function deactivate(int $id): void
    {
        $stmt = $this->db->prepare("UPDATE clients SET actif = 0 WHERE id = :id");
        $stmt->execute(['id' => $id]);
        $this->log($id, 'desactivation', 'Client désactivé');
    }

    public function history(int $id): array
    {
        $stmt = $this->db->prepare("SELECT * FROM clients_historique WHERE client_id = :id ORDER BY date_action DESC");
        $stmt->execute(['id' => $id]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    private function log(int $clientId, string $action, string $commentaire): void
    {
        $stmt = $this->db->prepare("INSERT INTO clients_historique (client_id, action, commentaire) VALUES (:client_id, :action, :commentaire)");
        $stmt->execute([
            'client_id' => $clientId,
            'action' => $action,
            'commentaire' => $commentaire,
        ]);
    }

    private function normalize(array $data): array
    {
        return [
            'type_client_id' => ($data['type_client_id'] ?? '') !== '' ? (int) $data['type_client_id'] : null,
            'code_client' => trim((string) ($data['code_client'] ?? '')),
            'raison_sociale' => trim((string) ($data['raison_sociale'] ?? '')),
            'contact' => trim((string) ($data['contact'] ?? '')),
            'adresse' => trim((string) ($data['adresse'] ?? '')),
            'code_postal' => trim((string) ($data['code_postal'] ?? '')),
            'ville' => trim((string) ($data['ville'] ?? '')),
            'pays' => trim((string) ($data['pays'] ?? 'Maroc')) ?: 'Maroc',
            'telephone' => trim((string) ($data['telephone'] ?? '')),
            'mobile' => trim((string) ($data['mobile'] ?? '')),
            'email' => trim((string) ($data['email'] ?? '')),
            'site_web' => trim((string) ($data['site_web'] ?? '')),
            'ice' => trim((string) ($data['ice'] ?? '')),
            'identifiant_fiscal' => trim((string) ($data['identifiant_fiscal'] ?? '')),
            'registre_commerce' => trim((string) ($data['registre_commerce'] ?? '')),
            'commercial' => trim((string) ($data['commercial'] ?? '')),
            'remise' => (float) ($data['remise'] ?? 0),
            'mode_reglement' => trim((string) ($data['mode_reglement'] ?? '')),
            'delai_paiement' => (int) ($data['delai_paiement'] ?? 0),
            'plafond_credit' => (float) ($data['plafond_credit'] ?? 0),
            'observations' => trim((string) ($data['observations'] ?? '')),
        ];
    }
}
