<?php
/**
 * This file is part of FacturaScripts
 * Copyright (C) 2021-2026 Carlos Garcia Gomez <carlos@facturascripts.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

namespace FacturaScripts\Core\Lib\AjaxForms;

use FacturaScripts\Core\Contract\PurchasesModInterface;
use FacturaScripts\Core\DataSrc\Paises;
use FacturaScripts\Core\DataSrc\Provincias;
use FacturaScripts\Core\Model\Base\PurchaseDocument;
use FacturaScripts\Core\Session;
use FacturaScripts\Core\Tools;
use FacturaScripts\Dinamic\Model\Ciudad;
use FacturaScripts\Dinamic\Model\Pais;
use FacturaScripts\Dinamic\Model\Proveedor;

/**
 * Description of PurchasesHeaderHTML
 *
 * @author Carlos Garcia Gomez           <carlos@facturascripts.com>
 * @author Jose Antonio Cuello Principal <yopli2000@gmail.com>
 * @author Daniel Fernández Giménez      <contacto@danielfg.es>
 */
class PurchasesHeaderHTML
{
    use CommonSalesPurchases;

    /** @var PurchasesModInterface[] */
    private static $mods = [];

    public static function addMod(PurchasesModInterface $mod): void
    {
        self::$mods[] = $mod;
    }

    public static function apply(PurchaseDocument &$model, array $formData): void
    {
        // mods
        foreach (self::$mods as $mod) {
            $mod->applyBefore($model, $formData);
        }

        $proveedor = new Proveedor();
        if (empty($model->id())) {
            // new record. Sets user and supplier
            $model->setAuthor(Session::user());
            if (isset($formData['codproveedor']) && $formData['codproveedor'] && $proveedor->load($formData['codproveedor'])) {
                $model->setSubject($proveedor);
                if (empty($formData['action']) || $formData['action'] === 'set-supplier') {
                    return;
                }
            }
        } elseif (
            isset($formData['action'], $formData['codproveedor']) &&
            $formData['action'] === 'set-supplier' &&
            $proveedor->load($formData['codproveedor'])
        ) {
            // existing record and change supplier
            $model->setSubject($proveedor);
            return;
        }

        $model->setWarehouse($formData['codalmacen'] ?? $model->codalmacen);
        $model->cifnif = $formData['cifnif'] ?? $model->cifnif;
        $model->coddivisa = $formData['coddivisa'] ?? $model->coddivisa;
        $model->codpago = $formData['codpago'] ?? $model->codpago;
        $model->codproveedor = $formData['codproveedor'] ?? $model->codproveedor;
        $model->codserie = $formData['codserie'] ?? $model->codserie;
        $model->fecha = empty($formData['fecha']) ? $model->fecha : Tools::date($formData['fecha']);
        $model->femail = isset($formData['femail']) && !empty($formData['femail']) ? $formData['femail'] : $model->femail;
        $model->hora = $formData['hora'] ?? $model->hora;
        $model->nombre = $formData['nombre'] ?? $model->nombre;
        $model->numproveedor = $formData['numproveedor'] ?? $model->numproveedor;
        $model->operacion = $formData['operacion'] ?? $model->operacion;
        $model->tasaconv = (float)($formData['tasaconv'] ?? $model->tasaconv);
        $model->apartado = $formData['apartado'] ?? $model->apartado;
        $model->ciudad = $formData['ciudad'] ?? $model->ciudad;
        $model->codpais = $formData['codpais'] ?? $model->codpais;
        $model->codpostal = $formData['codpostal'] ?? $model->codpostal;
        $model->direccion = $formData['direccion'] ?? $model->direccion;
        $model->provincia = $formData['provincia'] ?? $model->provincia;

        foreach (['fechadevengo'] as $key) {
            if (isset($formData[$key])) {
                $model->{$key} = empty($formData[$key]) ? null : $formData[$key];
            }
        }

        // mods
        foreach (self::$mods as $mod) {
            $mod->apply($model, $formData);
        }
    }

    public static function assets(): void
    {
        // mods
        foreach (self::$mods as $mod) {
            $mod->assets();
        }
    }

    public static function render(PurchaseDocument $model): string
    {
        return '<div class="container-fluid">'
            . '<div class="row g-2 align-items-end">'
            . self::renderField($model, 'codproveedor')
            . self::renderField($model, 'codalmacen')
            . self::renderField($model, 'codserie')
            . self::renderField($model, 'fecha')
            . self::renderNewFields($model)
            . self::renderField($model, 'numproveedor')
            . self::renderField($model, 'codpago')
            . self::renderField($model, 'total')
            . '</div>'
            . '<div class="row g-2 align-items-end">'
            . self::renderField($model, '_detail')
            . self::renderField($model, '_parents')
            . self::renderField($model, '_children')
            . self::renderField($model, '_email')
            . self::renderNewBtnFields($model)
            . self::renderField($model, '_paid')
            . self::renderField($model, 'idestado')
            . '</div>'
            . '</div>';
    }

    private static function codproveedor(PurchaseDocument $model): string
    {
        $proveedor = new Proveedor();
        if (empty($model->codproveedor) || false === $proveedor->load($model->codproveedor)) {
            return '<div class="col-sm-6 col-md-4 col-lg-3">'
                . '<div class="mb-2">' . Tools::trans('supplier')
                . '<input type="hidden" name="codproveedor" />'
                . '<a href="#" id="btnFindSupplierModal" class="btn btn-primary w-100" onclick="$(\'#findSupplierModal\').modal(\'show\');'
                . ' $(\'#findSupplierInput\').focus(); return false;"><i class="fa-solid fa-users fa-fw me-1"></i> '
                . Tools::trans('select') . '</a>'
                . '</div>'
                . '</div>'
                . self::detailModal($model);
        }

        $btnProveedor = $model->editable ?
            '<button class="btn btn-outline-secondary" type="button" onclick="$(\'#findSupplierModal\').modal(\'show\');'
            . ' $(\'#findSupplierInput\').focus(); return false;"><i class="fa-solid fa-pen"></i></button>' :
            '<button class="btn btn-outline-secondary" type="button"><i class="fa-solid fa-lock"></i></button>';

        $html = '<div class="col-sm-6 col-md-4 col-lg">'
            . '<div class="mb-2">'
            . '<a href="' . $proveedor->url() . '">' . Tools::trans('supplier') . '</a>'
            . '<input type="hidden" name="codproveedor" value="' . $model->codproveedor . '" />'
            . '<div class="input-group">'
            . '<input type="text" value="' . Tools::noHtml($proveedor->nombre) . '" class="form-control" readonly />'
            . '' . $btnProveedor . ''
            . '</div>'
            . '</div>'
            . '</div>';

        if (empty($model->id())) {
            $html .= self::detail($model, true);
        }

        return $html;
    }

    private static function detail(PurchaseDocument $model, bool $new = false): string
    {
        if (empty($model->id()) && $new === false) {
            // si el modelo es nuevo, ya hemos pintado el modal de detalle
            return '';
        }

        $css = $new ? 'col-sm-auto' : 'col-sm';
        return '<div class="' . $css . '">'
            . '<div class="mb-2">'
            . '<button class="btn btn-outline-secondary" type="button" data-bs-toggle="modal" data-bs-target="#headerModal">'
            . '<i class="fa-solid fa-edit fa-fw" aria-hidden="true"></i> ' . Tools::trans('detail') . ' </button>'
            . '</div>'
            . '</div>'
            . self::detailModal($model);
    }

    private static function detailModal(PurchaseDocument $model): string
    {
        return '<div class="modal fade" id="headerModal" tabindex="-1" aria-labelledby="headerModalLabel" aria-hidden="true">'
            . '<div class="modal-dialog modal-dialog-centered">'
            . '<div class="modal-content">'
            . '<div class="modal-header">'
            . '<h5 class="modal-title">' . Tools::trans('detail') . '</h5>'
            . '<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">'
            . ''
            . '</button>'
            . '</div>'
            . '<div class="modal-body">'
            . '<div class="row g-2">'
            . self::renderField($model, 'nombre')
            . self::renderField($model, 'cifnif')
            . self::renderField($model, 'direccion')
            . self::renderField($model, 'apartado')
            . self::renderField($model, 'codpostal')
            . self::renderField($model, 'ciudad')
            . self::renderField($model, 'provincia')
            . self::renderField($model, 'codpais')
            . self::renderField($model, 'fechadevengo')
            . self::renderField($model, 'hora')
            . self::renderField($model, 'operacion')
            . self::renderField($model, 'femail')
            . self::renderField($model, 'coddivisa')
            . self::renderField($model, 'tasaconv')
            . self::renderField($model, 'user')
            . self::renderNewModalFields($model)
            . '</div>'
            . '</div>'
            . '<div class="modal-footer">'
            . '<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">' . Tools::trans('close') . '</button>'
            . '<button type="button" class="btn btn-primary" data-bs-dismiss="modal">' . Tools::trans('accept') . '</button>'
            . '</div>'
            . '</div>'
            . '</div>'
            . '</div>';
    }

    private static function addressField(PurchaseDocument $model, string $field, string $label, int $size, int $maxlength): string
    {
        $attributes = $model->editable ?
            'name="' . $field . '" maxlength="' . $maxlength . '" autocomplete="off"' :
            'disabled=""';

        return '<div class="col-sm-' . $size . '">'
            . '<div class="mb-2">' . Tools::trans($label)
            . '<input type="text" ' . $attributes . ' value="' . Tools::noHtml($model->{$field}) . '" class="form-control"/>'
            . '</div>'
            . '</div>';
    }

    private static function ciudad(PurchaseDocument $model, int $size, int $maxlength): string
    {
        $list = '';
        $dataList = '';
        $attributes = $model->editable ?
            'name="ciudad" maxlength="' . $maxlength . '" autocomplete="off"' :
            'disabled=""';

        if ($model->editable) {
            $list = 'list="purchases-ciudades"';
            $dataList = '<datalist id="purchases-ciudades">';

            foreach (Ciudad::all([], ['ciudad' => 'ASC'], 0, 0) as $ciudad) {
                $dataList .= '<option value="' . Tools::noHtml($ciudad->ciudad) . '">' . Tools::noHtml($ciudad->ciudad) . '</option>';
            }
            $dataList .= '</datalist>';
        }

        return '<div class="col-sm-' . $size . '">'
            . '<div class="mb-2">' . Tools::trans('city')
            . '<input type="text" ' . $attributes . ' value="' . Tools::noHtml($model->ciudad) . '" ' . $list . ' class="form-control"/>'
            . $dataList
            . '</div>'
            . '</div>';
    }

    private static function codpais(PurchaseDocument $model): string
    {
        $options = ['<option value="">------</option>'];
        foreach (Paises::all() as $pais) {
            $options[] = ($pais->codpais === $model->codpais) ?
                '<option value="' . $pais->codpais . '" selected>' . $pais->nombre . '</option>' :
                '<option value="' . $pais->codpais . '">' . $pais->nombre . '</option>';
        }

        $pais = new Pais();
        $attributes = $model->editable ? 'name="codpais"' : 'disabled=""';
        return '<div class="col-sm-6">'
            . '<div class="mb-2">'
            . '<a href="' . $pais->url() . '">' . Tools::trans('country') . '</a>'
            . '<select ' . $attributes . ' class="form-select">' . implode('', $options) . '</select>'
            . '</div>'
            . '</div>';
    }

    private static function nombre(PurchaseDocument $model): string
    {
        $attributes = $model->editable ? 'name="nombre" required' : 'disabled';
        return '<div class="col-sm-6">'
            . '<div class="mb-2">' . Tools::trans('business-name')
            . '<input type="text" ' . $attributes . ' value="' . Tools::noHtml($model->nombre) . '" class="form-control" maxlength="100" autocomplete="off"/>'
            . '</div>'
            . '</div>';
    }

    private static function numproveedor(PurchaseDocument $model): string
    {
        $attributes = $model->editable ? 'name="numproveedor"' : 'disabled';
        return empty($model->codproveedor) ? '' : '<div class="col-sm-6 col-md-4 col-lg">'
            . '<div class="mb-2">' . Tools::trans('numsupplier')
            . '<input type="text" ' . $attributes . ' value="' . Tools::noHtml($model->numproveedor) . '" class="form-control" maxlength="50"'
            . ' placeholder="' . Tools::trans('optional') . '" />'
            . '</div>'
            . '</div>';
    }

    private static function provincia(PurchaseDocument $model, int $size, int $maxlength): string
    {
        $list = '';
        $dataList = '';
        $attributes = $model->editable ?
            'name="provincia" maxlength="' . $maxlength . '" autocomplete="off"' :
            'disabled=""';

        if ($model->editable) {
            $list = 'list="purchases-provincias"';
            $dataList = '<datalist id="purchases-provincias">';

            foreach (Provincias::all() as $provincia) {
                $dataList .= '<option value="' . Tools::noHtml($provincia->provincia) . '">' . Tools::noHtml($provincia->provincia) . '</option>';
            }
            $dataList .= '</datalist>';
        }

        return '<div class="col-sm-' . $size . '">'
            . '<div class="mb-2">' . Tools::trans('province')
            . '<input type="text" ' . $attributes . ' value="' . Tools::noHtml($model->provincia) . '" ' . $list . ' class="form-control"/>'
            . $dataList
            . '</div>'
            . '</div>';
    }

    private static function renderField(PurchaseDocument $model, string $field): ?string
    {
        foreach (self::$mods as $mod) {
            $html = $mod->renderField($model, $field);
            if ($html !== null) {
                return $html;
            }
        }

        switch ($field) {
            case '_children':
                return self::children($model);

            case '_detail':
                return self::detail($model);

            case '_email':
                return self::email($model);

            case '_fecha':
                return self::fecha($model, false);

            case '_paid':
                return self::paid($model);

            case '_parents':
                return self::parents($model);

            case 'apartado':
                return self::addressField($model, 'apartado', 'post-office-box', 4, 10);

            case 'cifnif':
                return self::cifnif($model);

            case 'ciudad':
                return self::ciudad($model, 4, 100);

            case 'codalmacen':
                return self::codalmacen($model, 'purchasesFormAction');

            case 'coddivisa':
                return self::coddivisa($model);

            case 'codpago':
                return self::codpago($model);

            case 'codpais':
                return self::codpais($model);

            case 'codpostal':
                return self::addressField($model, 'codpostal', 'zip-code', 4, 10);

            case 'codproveedor':
                return self::codproveedor($model);

            case 'codserie':
                return self::codserie($model, 'purchasesFormAction');

            case 'direccion':
                return self::addressField($model, 'direccion', 'address', 12, 200);

            case 'fecha':
                return self::fecha($model);

            case 'fechadevengo':
                return self::fechadevengo($model);

            case 'femail':
                return self::femail($model);

            case 'hora':
                return self::hora($model);

            case 'idestado':
                return self::idestado($model, 'purchasesFormSave');

            case 'nombre':
                return self::nombre($model);

            case 'numproveedor':
                return self::numproveedor($model);

            case 'operacion':
                return self::operacion($model);

            case 'provincia':
                return self::provincia($model, 6, 100);

            case 'tasaconv':
                return self::tasaconv($model);

            case 'total':
                return self::total($model, 'purchasesFormSave');

            case 'user':
                return self::user($model);
        }

        return null;
    }

    private static function renderNewBtnFields(PurchaseDocument $model): string
    {
        // cargamos los nuevos campos
        $newFields = [];
        foreach (self::$mods as $mod) {
            foreach ($mod->newBtnFields() as $field) {
                if (false === in_array($field, $newFields)) {
                    $newFields[] = $field;
                }
            }
        }

        // renderizamos los campos
        $html = '';
        foreach ($newFields as $field) {
            foreach (self::$mods as $mod) {
                $fieldHtml = $mod->renderField($model, $field);
                if ($fieldHtml !== null) {
                    $html .= $fieldHtml;
                    break;
                }
            }
        }
        return $html;
    }

    private static function renderNewFields(PurchaseDocument $model): string
    {
        // cargamos los nuevos campos
        $newFields = [];
        foreach (self::$mods as $mod) {
            foreach ($mod->newFields() as $field) {
                if (false === in_array($field, $newFields)) {
                    $newFields[] = $field;
                }
            }
        }

        // renderizamos los campos
        $html = '';
        foreach ($newFields as $field) {
            foreach (self::$mods as $mod) {
                $fieldHtml = $mod->renderField($model, $field);
                if ($fieldHtml !== null) {
                    $html .= $fieldHtml;
                    break;
                }
            }
        }
        return $html;
    }

    private static function renderNewModalFields(PurchaseDocument $model): string
    {
        // cargamos los nuevos campos
        $newFields = [];
        foreach (self::$mods as $mod) {
            foreach ($mod->newModalFields() as $field) {
                if (false === in_array($field, $newFields)) {
                    $newFields[] = $field;
                }
            }
        }

        // renderizamos los campos
        $html = '';
        foreach ($newFields as $field) {
            foreach (self::$mods as $mod) {
                $fieldHtml = $mod->renderField($model, $field);
                if ($fieldHtml !== null) {
                    $html .= $fieldHtml;
                    break;
                }
            }
        }
        return $html;
    }
}
