<?php

require_once __DIR__ . '/../../core/database.php';
require_once __DIR__ . '/../../core/format.php';
require_once __DIR__ . '/FactoClient.php';
require_once __DIR__ . '/../billing/BillingRuntimeGate.php';

class FactoCustomersSyncService
{
    private $pdo;
    private $client;
    private $environment;

    public function __construct($environment = null)
    {
        $this->environment = billing_runtime_environment($environment);
        $this->pdo = db();
        $this->client = new FactoClient($this->environment);
    }

    public function syncCustomers($perPage = 100, $forceFullSync = false)
    {
        billing_assert_runtime_operation('sync', $this->environment, 'Sincronización de clientes y proveedores FACTO');
        $page = 1;
        $totalCreated = 0;
        $totalUpdated = 0;
        $totalSkipped = 0;

        do {
            $response = $this->client->getCustomersSuppliers(array(
                'page' => $page,
                'per_page' => $perPage,
                'status' => 1
            ));

            $items = array();

            if (isset($response['_embedded']['customers_suppliers']) && is_array($response['_embedded']['customers_suppliers'])) {
                $items = $response['_embedded']['customers_suppliers'];
            }

            foreach ($items as $item) {
                $isCustomer = isset($item['is_customer']) ? (int) $item['is_customer'] : 0;

                if ($isCustomer !== 1) {
                    continue;
                }

                $factoId = $this->pick($item, 'customer_supplier_id');

                if (!$factoId) {
                    continue;
                }

                $exists = $this->customerExists($factoId);

                if ($exists && !$forceFullSync) {
                    $totalSkipped++;
                    continue;
                }

                $detail = $this->client->getCustomerSupplier($factoId);
                $result = $this->saveCustomer($detail);

                if ($result === 'created') {
                    $totalCreated++;
                } elseif ($result === 'updated') {
                    $totalUpdated++;
                }
            }

            $pageCount = isset($response['page_count']) ? (int) $response['page_count'] : 1;
            $page++;

        } while ($page <= $pageCount);

        $this->log(
            'success',
            'Clientes FACTO sincronizados. Nuevos: ' . $totalCreated .
            ' | Actualizados: ' . $totalUpdated .
            ' | Omitidos: ' . $totalSkipped
        );

        return array(
            'created' => $totalCreated,
            'updated' => $totalUpdated,
            'skipped' => $totalSkipped
        );
    }

    private function saveCustomer($c)
    {
        $factoId = $this->pick($c, 'customer_supplier_id');
        $commercialName = $this->pick($c, 'name');
        $responsibleUserId = $this->pick($c, 'responsible_user_id');
        $paymentTerm = $this->pick($c, 'payment_term');

        if (!$factoId || !$commercialName) {
            return 'skipped';
        }

        $alreadyExists = $this->customerExists($factoId);

        $contact = array();
        if (isset($c['contacts'][0]) && is_array($c['contacts'][0])) {
            $contact = $c['contacts'][0];
        }

        $invoicing = array();
        if (isset($c['invoicing_details'][0]) && is_array($c['invoicing_details'][0])) {
            $invoicing = $c['invoicing_details'][0];
        }

        $contactFirstName = $this->pick($contact, 'first_name');
        $contactLastName = $this->pick($contact, 'last_name');
        $contactName = trim((string) $contactFirstName . ' ' . (string) $contactLastName);
        $contactEmail = $this->pick($contact, 'email');
        $contactPhone = $this->pick($contact, 'phone');
        $contactId = $this->pick($contact, 'customer_supplier_contact_id');

        $invoicingDetailsId = $this->pick($invoicing, 'invoicing_details_id');
        $countryId = $this->pick($invoicing, 'country_id');
        $countryName = $this->countryNameFromFactoId($countryId);
        $taxIdType = $this->pick($invoicing, 'tax_id_type');
        $taxIdCode = $this->pick($invoicing, 'tax_id_code');
        $isExportIdentity = ($countryId !== null && (int)$countryId !== 253)
            || ($taxIdType !== null && strtoupper((string)$taxIdType) !== 'CL-RUT');
        $exportTaxIdCode = $isExportIdentity ? $taxIdCode : null;
        $exportTaxIdType = $isExportIdentity ? $taxIdType : null;
        $exportCountryId = $isExportIdentity ? $countryId : null;
        $legalName = $this->pick($invoicing, 'legal_name');
        $address = $this->pick($invoicing, 'address');
        $district = $this->pick($invoicing, 'district');
        $city = $this->pick($invoicing, 'city');
        $businessActivity = $this->pick($invoicing, 'business_activity');
        $invoicingPhone = $this->pick($invoicing, 'phone');

        if (!$legalName) {
            $legalName = $commercialName;
        }

        $phone = $contactPhone ? $contactPhone : $invoicingPhone;

        $stmt = $this->pdo->prepare("
            INSERT INTO crm_customers
            (
                facto_customer_supplier_id,
                customer_name,
                commercial_name,
                legal_name,
                customer_tax_id,
                export_tax_id_code,
                export_tax_id_type,
                export_country_id,
                invoicing_details_id,
                tax_id_type,
                contact_name,
                contact_first_name,
                contact_last_name,
                email,
                phone,
                address,
                district,
                city,
                country,
                country_id,
                business_activity,
                website,
                owner_name,
                source,
                facto_responsible_user_id,
                facto_payment_term,
                payment_terms,
                facto_contact_id,
                notes
            )
            VALUES
            (
                ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
            )
            ON DUPLICATE KEY UPDATE
                customer_name = VALUES(customer_name),
                commercial_name = VALUES(commercial_name),
                legal_name = VALUES(legal_name),
                customer_tax_id = VALUES(customer_tax_id),
                export_tax_id_code = COALESCE(VALUES(export_tax_id_code), export_tax_id_code),
                export_tax_id_type = COALESCE(VALUES(export_tax_id_type), export_tax_id_type),
                export_country_id = COALESCE(VALUES(export_country_id), export_country_id),
                invoicing_details_id = VALUES(invoicing_details_id),
                tax_id_type = VALUES(tax_id_type),
                contact_name = VALUES(contact_name),
                contact_first_name = VALUES(contact_first_name),
                contact_last_name = VALUES(contact_last_name),
                email = VALUES(email),
                phone = VALUES(phone),
                address = VALUES(address),
                district = VALUES(district),
                city = VALUES(city),
                country = VALUES(country),
                country_id = VALUES(country_id),
                business_activity = VALUES(business_activity),
                source = VALUES(source),
                facto_responsible_user_id = VALUES(facto_responsible_user_id),
                facto_payment_term = VALUES(facto_payment_term),
                payment_terms = VALUES(payment_terms),
                facto_contact_id = VALUES(facto_contact_id),
                updated_at = CURRENT_TIMESTAMP
        ");

        $stmt->execute(array(
            $factoId,
            $commercialName,
            $commercialName,
            $legalName,
            $taxIdCode,
            $exportTaxIdCode,
            $exportTaxIdType,
            $exportCountryId,
            $invoicingDetailsId,
            $taxIdType,
            $contactName,
            $contactFirstName,
            $contactLastName,
            $contactEmail,
            $phone,
            $address,
            $district,
            $city,
            $countryName,
            $countryId,
            $businessActivity,
            null,
            null,
            'facto',
            $responsibleUserId,
            $paymentTerm,
            icylab_normalize_payment_terms($paymentTerm),
            $contactId,
            'Sincronizado desde FACTO'
        ));

        return $alreadyExists ? 'updated' : 'created';
    }


    private function countryNameFromFactoId($countryId)
    {
        $id = $countryId !== null ? (int) $countryId : 0;

        $map = array(
            253 => 'Chile',
            88 => 'Argentina',
            83 => 'Perú',
            87 => 'Uruguay',
            65 => 'Venezuela',
            66 => 'Colombia',
            82 => 'Ecuador',
            80 => 'México',
            81 => 'Bolivia',
            84 => 'Paraguay',
            85 => 'Brasil',
            90 => 'Estados Unidos',
            198 => 'España'
        );

        if ($id === 0) return null;
        return isset($map[$id]) ? $map[$id] : 'Exterior';
    }

    private function customerExists($factoId)
    {
        $stmt = $this->pdo->prepare("
            SELECT id
            FROM crm_customers
            WHERE facto_customer_supplier_id = ?
            LIMIT 1
        ");

        $stmt->execute(array($factoId));

        return $stmt->fetch() ? true : false;
    }

    private function pick($array, $key)
    {
        return isset($array[$key]) && $array[$key] !== '' ? $array[$key] : null;
    }

    private function log($status, $message)
    {
        $stmt = $this->pdo->prepare("
            INSERT INTO facto_sync_logs (status, message)
            VALUES (?, ?)
        ");

        $stmt->execute(array($status, $message));
    }
}