<?php
require_once __DIR__ . '/../../../../vendor/autoload.php';

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\IOFactory;

class PlanillaUnica
{
    public $id;
    public $fechaDescarga;
    public $tipoPlanilla;
    public $periodo;
    public $fechaRegistro;
    public $usuario;
    public $empleados = [];

    function __construct()
    {
        !empty($this->fechaDescarga) && $this->fechaDescarga = date("d-m-Y h:i a", strtotime($this->fechaDescarga));
    }

    public static function buscar(int $codtipoplanilla, string $periodo, bool $datosNuevos = false): object
    {
        $db = obtenerConexion();

        $query = "SELECT TOP(1) encabezado.id FROM rrhh.datos_planillaUnica encabezado WHERE encabezado.codtipoplanilla = :codtipoplanilla AND encabezado.periodo = :periodo AND (SELECT count(*) FROM rrhh.det_planillaUnica WHERE idPlanillaUnica = encabezado.id) > 0 ORDER BY id DESC;";
        $stmt = $db->prepare($query, [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);
        $stmt->bindParam(":codtipoplanilla", $codtipoplanilla, PDO::PARAM_INT);
        $stmt->bindParam(":periodo", $periodo, PDO::PARAM_STR);

        try {
            $stmt->execute();

            $ultimaGeneracion = $stmt->fetch(PDO::FETCH_OBJ);
            $id = null;

            if (!empty($ultimaGeneracion)) {
                $id = $ultimaGeneracion->id;
            }

            $stmt->closeCursor();

            if (empty($id) || $datosNuevos) {
                $query = "SELECT * FROM rrhh.view_datosProyeccionPlanillaUnica WHERE codtipoplanilla = :codtipoplanilla AND periodo = :periodo;";
                $stmt = $db->prepare($query, [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);
                $stmt->bindParam(":codtipoplanilla", $codtipoplanilla, PDO::PARAM_INT);
                $stmt->bindParam(":periodo", $periodo, PDO::PARAM_STR);
            } else {
                $query = "SELECT * FROM rrhh.det_planillaUnica WHERE idPlanillaUnica = :id;";
                $stmt = $db->prepare($query, [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);
                $stmt->bindParam(":id", $id, PDO::PARAM_INT);
            }

            $stmt->execute();

            $data = $stmt->fetchAll(PDO::FETCH_OBJ);

            return (object)[
                "status" => 200,
                "data" => $data
            ];
        } catch (PDOException $e) {
            return (object)[
                "status" => 500,
                "message" => $e->getMessage()
            ];
        }
    }

    public function guardar(int $usuario, string $tipoArchivo = "excel"): object
    {
        $db = obtenerConexion();

        $db->beginTransaction();

        $respuesta = null;
        $id = null;
        try {
            $query = "EXEC rrhh.sp_guardarPlanillaUnica :id,:tipoPlanilla,:periodo,:usuario,:respuesta,:idPlanillaUnica;";

            $stmt = $db->prepare($query, [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);
            $stmt->bindParam(":id", $this->id, PDO::PARAM_INT);
            $stmt->bindParam(":tipoPlanilla", $this->tipoPlanilla, PDO::PARAM_INT);
            $stmt->bindParam(":periodo", $this->periodo, PDO::PARAM_STR);
            $stmt->bindParam(":usuario", $usuario, PDO::PARAM_INT);
            $stmt->bindParam(":respuesta", $respuesta, PDO::PARAM_STR | PDO::PARAM_INPUT_OUTPUT, 300);
            $stmt->bindParam(":idPlanillaUnica", $id, PDO::PARAM_INT | PDO::PARAM_INPUT_OUTPUT, 4000);

            $stmt->execute();

            $nombreArchivo = null;

            if ($respuesta == 'success') {
                $query = "DELETE FROM rrhh.det_planillaUnica WHERE idPlanillaUnica = :idPlanillaUnica;";
                $stmt = $db->prepare($query, [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);
                $stmt->bindParam(":idPlanillaUnica", $id, PDO::PARAM_INT);
                $stmt->execute();

                $limiteQuery = 8000;

                $encabezadoQuery = "INSERT INTO rrhh.det_planillaUnica(idPlanillaUnica,codempleado,tipoDocumento,numeroDocumento,documentoEmpleador,numeroPatronalEmpleador,correlativoTrabajo,codtipoplanilla,primerNombre,segundoNombre,primerApellido,segundoApellido,apellidoCasada,numeroPatronalEmpleado,institucionPrevisional,anio,periodo,salario,pagoAdicional,dias,horas,horasExtra,diasVacacion,montoVacaciones,codigo1,codigo2,idUsuario) VALUES";
                $arrEmpleados = [];

                foreach ($this->empleados as $empleado) {
                    $datosEmpleado = "(" . $id . ",'" . $empleado["codempleado"] . "'," . "'" . $empleado["tipoDocumento"] . "'," . "'" . $empleado["numeroDocumento"] . "'," . "'" . $empleado["documentoEmpleador"] . "'," . "'" . $empleado["numeroPatronalEmpleador"] . "'," . "'" . $empleado["correlativoTrabajo"] . "'," . "'" . $empleado["codtipoplanilla"] . "'," . "'" . $empleado["primerNombre"] . "'," . "'" . $empleado["segundoNombre"] . "'," . "'" . $empleado["primerApellido"] . "'," . "'" . $empleado["segundoApellido"] . "'," . "'" . $empleado["apellidoCasada"] . "'," . "'" . $empleado["numeroPatronalEmpleado"] . "'," . "'" . $empleado["institucionPrevisional"] . "'," . "'" . $empleado["anio"] . "'," . "'" . $empleado["periodo"] . "'," . "'" . $empleado["salario"] . "'," . "'" . $empleado["pagoAdicional"] . "'," . "'" . $empleado["dias"] . "'," . "'" . $empleado["horas"] . "'," . "'" . $empleado["horasExtra"] . "'," . "'" . $empleado["diasVacacion"] . "'," . "'" . $empleado["montoVacaciones"] . "'," . "'" . $empleado["codigo1"] . "'," . "'" . $empleado["codigo2"] . "'," . "'" . $usuario . "')";

                    if (strlen($encabezadoQuery) + strlen(implode(",", $arrEmpleados)) + strlen($datosEmpleado) >= 8000) {
                        $query = $encabezadoQuery . implode(",", $arrEmpleados) . ";";
                        $stmt = $db->prepare($query, [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);
                        $stmt->execute();

                        $arrEmpleados = [];
                    }

                    $arrEmpleados[] = $datosEmpleado;
                }

                if (count($arrEmpleados) > 0) {
                    $query = $encabezadoQuery . implode(",", $arrEmpleados) . ";";
                    $stmt = $db->prepare($query, [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);
                    $stmt->execute();
                }

                $respuestaArchivo = $tipoArchivo == 'csv' ? $this->crearCSV() : $this->crearExcel();

                $nombreArchivo = $respuestaArchivo->status == 200 ? $respuestaArchivo->nombreArchivo : "";
            }

            $db->commit();

            return (object)[
                "status" => 200,
                "message" => $respuesta,
                "id" => $id,
                "nombreArchivo" => $nombreArchivo
            ];
        } catch (PDOException $e) {
            $db->rollBack();
            return (object)[
                "status" => 500,
                "message" => $e->getMessage()
            ];
        }
    }

    private function crearExcel(): object
    {
        $nombreArchivo = "planillaUnica_" . $this->tipoPlanilla . $this->periodo . date("YmdHi") . ".xlsx";
        $directorio = __DIR__ . "/../../docs/planillaUnica/excel/";

        if (!is_dir($directorio)) mkdir($directorio, 0777, true);

        $spreadsheet = new Spreadsheet();

        $hojaCalculo = $spreadsheet->getActiveSheet();

        $hojaCalculo->setCellValue("A1", "DOCUMENTO EMPLEADOR");
        $hojaCalculo->setCellValue("B1", "NÚMERO PATRONAL EMPLEADOR");
        $hojaCalculo->setCellValue("C1", "PERIODO");
        $hojaCalculo->setCellValue("D1", "CORRELATIVO CENTRO DE TRABAJO");
        $hojaCalculo->setCellValue("E1", "DOCUMENTO AFILIADO");
        $hojaCalculo->setCellValue("F1", "TIPO DE DOCUMENTO AFILIADO");
        $hojaCalculo->setCellValue("G1", "NUMERO PATRONAL AFILIADO");
        $hojaCalculo->setCellValue("H1", "INSTITUCION PREVISIONAL");
        $hojaCalculo->setCellValue("I1", "PRIMER NOMBRE");
        $hojaCalculo->setCellValue("J1", "SEGUNDO NOMBRE");
        $hojaCalculo->setCellValue("K1", "PRIMER APELLIDO");
        $hojaCalculo->setCellValue("L1", "SEGUNDO APELLIDO");
        $hojaCalculo->setCellValue("M1", "APELLIDO DE CASADA");
        $hojaCalculo->setCellValue("N1", "SALARIO");
        $hojaCalculo->setCellValue("O1", "PAGO ADICIONAL");
        $hojaCalculo->setCellValue("P1", "MONTO DE VACACION");
        $hojaCalculo->setCellValue("Q1", "DIAS");
        $hojaCalculo->setCellValue("R1", "HORAS");
        $hojaCalculo->setCellValue("S1", "DIAS VACACION");
        $hojaCalculo->setCellValue("T1", "CÓDIGO OBSERVACIÓN 1");
        $hojaCalculo->setCellValue("U1", "CÓDIGO OBSERVACIÓN 2");

        $numeroLinea = 2;

        foreach ($this->empleados as $empleado) {
            $fila = $this->prepararFilaParaArchivo($empleado);

            foreach (range('A', 'U') as $columna) {
                $hojaCalculo->setCellValue($columna . $numeroLinea, $fila[$columna]);
                $hojaCalculo->getColumnDimension($columna)->setAutoSize(true);
            }

            $numeroLinea++;
        }

        $writer = new Xlsx($spreadsheet);

        // $writer->setOption('charset', 'UTF-8');

        $writer->save($directorio . $nombreArchivo);

        return (object)["status" => 200, "message" => "success", "nombreArchivo" => $nombreArchivo];
    }

    private function crearCSV(): object
    {
        $nombreArchivo = "planillaUnica_" . $this->tipoPlanilla . $this->periodo . date("YmdHi") . ".csv";
        $directorio = __DIR__ . "/../../docs/planillaUnica/csv/";

        if (!is_dir($directorio)) mkdir($directorio, 0777, true);

        $ruta = $directorio . $nombreArchivo;
        $fp = fopen($ruta, "w");

        // fprintf($fp, chr(0xEF) . chr(0xBB) . chr(0xBF));

        foreach ($this->empleados as $empleado) {
            $linea = $this->prepararFilaParaArchivo($empleado);

            // fprintf($fp, chr(0xEF) . chr(0xBB) . chr(0xBF));
            fwrite($fp, implode(",", $linea) . PHP_EOL);
        }

        fclose($fp);

        mb_convert_encoding($ruta, 'UTF-16LE', 'UTF-8');

        return (object)["status" => 200, "message" => "success", "nombreArchivo" => $nombreArchivo];
    }

    private function prepararFilaParaArchivo($empleado): array
    {
        $primerNombre = trim($empleado["primerNombre"]);
        $segundoNombre = trim($empleado["segundoNombre"]);
        $primerApellido = trim($empleado["primerApellido"]);
        $segundoApellido = trim($empleado["segundoApellido"]);
        $apellidoCasada = trim($empleado["apellidoCasada"]);

        $arrApellidoCasada = explode(" ", $apellidoCasada);

        if (trim($arrApellidoCasada[0]) == "DE") {
            $apellidoCasada = trim($arrApellidoCasada[1]);
        }

        $linea = [
            'A' => strval(implode("", explode("-", $empleado["documentoEmpleador"]))),
            'B' => strval($empleado["numeroPatronalEmpleador"]),
            'C' => strval($empleado["periodo"]),
            'D' => strval($empleado["correlativoTrabajo"]),
            'E' => implode("", explode("-", $empleado["numeroDocumento"])),
            'F' => str_pad(intval($empleado["tipoDocumento"]), 2, "0", STR_PAD_LEFT),
            'G' => $empleado["numeroPatronalEmpleado"],
            'H' => $empleado["institucionPrevisional"] == '0' ? "" : $empleado["institucionPrevisional"],
            'I' => strlen($primerNombre) > 40 ? substr($primerNombre, 0, 40) : $primerNombre,
            'J' => strlen($segundoNombre) > 40 ? substr($segundoNombre, 0, 40) : $segundoNombre,
            'K' => strlen($primerApellido) > 40 ? substr($primerApellido, 0, 40) : $primerApellido,
            'L' => strlen($segundoApellido) > 40 ? substr($segundoApellido, 0, 40) : $segundoApellido,
            'M' => strlen($apellidoCasada) > 40 ? substr($apellidoCasada, 0, 40) : $apellidoCasada,
            'N' => number_format(floatval($empleado["salario"]), 2, ".", ""),
            'O' => number_format(floatval($empleado["pagoAdicional"]), 2, ".", ""),
            'P' => number_format(floatval($empleado["montoVacaciones"]), 2, ".", ""),
            'Q' => intval($empleado["dias"]),
            'R' => intval($empleado["horas"]),
            'S' => intval($empleado["diasVacacion"]),
            'T' => str_pad(intval($empleado["codigo1"]), 2, "0", STR_PAD_LEFT),
            'U' => str_pad(intval($empleado["codigo2"]), 2, "0", STR_PAD_LEFT),
        ];

        return $linea;
    }

    public static function buscarEmpleado($codempleado): object
    {
        $db = obtenerConexion();

        $query = "SELECT TOP(1) * FROM rrhh.view_empleadosPlanillaUnica WHERE codempleado = :codempleado;";
        $stmt = $db->prepare($query, [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);
        $stmt->bindParam(":codempleado", $codempleado, PDO::PARAM_STR);

        try {
            $stmt->execute();
            $empleado = $stmt->fetchAll(PDO::FETCH_OBJ);
            return (object)["status" => 200, "message" => "success", "data" => $empleado];
        } catch (PDOException $e) {
            return (object)["status" => 500, "message" => $e->getMessage()];
        }
    }
}
