<?php
namespace Incoviba\Repository\Venta;

use DateTimeImmutable;
use Incoviba\Common\Define;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Model;
use Incoviba\Repository;

class Factura extends Ideal\Repository
{
    public function __construct(Implement\Connection $connection, protected Repository\Venta $ventaRepository)
    {
        parent::__construct($connection);
        $this->setTable('facturas');
    }

    public function create(?array $data = null): Model\Venta\Factura
    {
        $map = (new Implement\Repository\MapperParser(['index']))
            ->register('venta_id', (new Implement\Repository\Mapper())
                ->setProperty('venta')
                ->setFunction(function($data) {
                    return $this->ventaRepository->fetchById($data['venta_id']);
                }));
        $factura = $this->parseData(new Model\Venta\Factura(), $data, $map);
        $json = json_decode($data['data']);
        $factura->proporcion = $json->proporcion;
        $factura->emisorRut = $json->emisor->rut;
        $factura->emisorNombre = $json->emisor->nombre;
        $factura->emisorDireccion = $json->emisor->direccion;
        $factura->receptorRut = $json->receptor->rut;
        $factura->receptorNombre = $json->receptor->nombre;
        $factura->receptorDireccion = $json->receptor->direccion;
        $factura->receptorComuna = $json->receptor->comuna;
        $factura->fecha = new DateTimeImmutable($json->fecha);
        $factura->unidades = $json->unidades;
        $factura->detalleBase = $json->detalle->base;
        $factura->detalleTerreno = $json->detalle->terreno;
        $factura->detalleNeto = $json->detalle->neto;
        $factura->detalleIva = $json->detalle->iva;
        $factura->detalleBruto = $json->detalle->bruto;
        $factura->detalleDescuento = $json->detalle->descuento;
        $factura->detalleTotal = $json->detalle->total;
        $factura->totalNeto = $json->total->neto;
        $factura->totalExento = $json->total->exento;
        $factura->totalIva = $json->total->iva;
        $factura->totalTotal = $json->total->total;
        $factura->fechaUF = new DateTimeImmutable($json->uf->fecha);
        $factura->valorUF = $json->uf->valor;
        return $factura;
    }
    public function save(Define\Model $model): Model\Venta\Factura
    {
        $model->id = $this->saveNew([
            'venta_id',
            'index',
            'data'
        ], [
            $model->venta->id,
            $model->index,
            json_encode([
                'proporcion' => $model->proporcion,
                'emisor' => [
                    'rut' => $model->emisorRut,
                    'nombre' => $model->emisorNombre,
                    'direccion' => $model->emisorDireccion
                ],
                'receptor' => [
                    'rut' => $model->receptorRut,
                    'nombre' => $model->receptorNombre,
                    'direccion' => $model->receptorDireccion,
                    'comuna' => $model->receptorComuna
                ],
                'fecha' => $model->fecha->format('Y-m-d'),
                'unidades' => $model->unidades,
                'detalle' => [
                    'base' => $model->detalleBase,
                    'terreno' => $model->detalleTerreno,
                    'neto' => $model->detalleNeto,
                    'iva' => $model->detalleIva,
                    'bruto' => $model->detalleBruto,
                    'descuento' => $model->detalleDescuento,
                    'total' => $model->detalleTotal
                ],
                'total' => [
                    'neto' => $model->totalNeto,
                    'exento' => $model->totalExento,
                    'iva' => $model->totalIva,
                    'total' => $model->totalTotal
                ],
                'uf' => [
                    'fecha' => $model->fechaUF->format('Y-m-d'),
                    'valor' => $model->valorUF
                ]
            ])
        ]);
        return $model;
    }
    public function edit(Define\Model $model, array $new_data): Model\Venta\Factura
    {
        return $this->update($model, ['venta_id', 'index', 'data'], $new_data);
    }

    /**
     * @throws EmptyResult
     */
    public function fetchByVenta(int $venta_id): array
    {
        $query = $this->connection->getQueryBuilder()
            ->select()
            ->from($this->getTable())
            ->where('venta_id = :venta_id');
        return $this->fetchMany($query, ['venta_id' => $venta_id]);
    }
    /**
     * @throws EmptyResult
     */
    public function fetchByVentaAndIndex(int $venta_id, int $index): Model\Venta\Factura
    {
        $query = $this->connection->getQueryBuilder()
            ->select()
            ->from($this->getTable())
            ->where('venta_id = :venta_id AND index = :index');
        return $this->fetchOne($query, ['venta_id' => $venta_id, 'index' => $index]);
    }
}
