<?php

namespace App\Http\Controllers;

use App\Helpers\FechaHelper;
use App\Helpers\SeguimientoHelper;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

/**
 * AjusteController
 * Módulo: ajustes/ del sistema original
 *
 * ── CRUD ─────────────────────────────────────────────────────────────────────
 *   index.php          → index()
 *   rejilla.php        → index() con paginación
 *   nuevo_ajuste.php   → create()
 *   guardar_ajuste.php → store()
 *   ver_ajuste.php     → show()
 *
 * ── REPORTES ─────────────────────────────────────────────────────────────────
 *   ajuste.php + pdf_ajuste.php           → ajustePdf()
 *   ajustesrealizados.php + pdf_ajuste... → realizadosForm() + realizadosPdf()
 *   ajustesxfecha.php                     → porFechaForm()  + porFecha()
 *
 * Los ajustes viven en la tabla extractos con:
 *   tipmov=5 → Ajuste Cargo  (cobro extra al cliente)
 *   tipmov=6 → Ajuste Abono  (descuento/crédito al cliente)
 *
 * Solo el administrador (tipo=1) puede crear ajustes.
 */
class AjusteController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }

    // =========================================================================
    // CRUD
    // =========================================================================

    // ── Listado ──────────────────────────────────────────────────────────────
public function index(Request $request)
{
    $buscar      = $request->input('buscar', '');
    $buscax      = $request->input('buscax', '1'); // 1 = Cliente, 2 = Contrato
    $tipo_ajuste = $request->input('tipo_ajuste'); // 5 = Cargo, 6 = Abono

    $query = DB::table('extractos')
        ->leftJoin('clientes', 'extractos.idcliente', '=', 'clientes.id')
        ->whereIn('extractos.tipmov', [5, 6]) // Solo ajustes
        ->where('extractos.anulado', 0)
        ->select('extractos.*', 'clientes.nombre as nom_cliente');

    // --- Filtro por Botones (Cargo/Abono) ---
    if ($tipo_ajuste) {
        $query->where('extractos.tipmov', $tipo_ajuste);
    }

    // --- Filtro por Buscador ---
    if ($buscar !== '') {
        if ($buscax == '1') {
            // Buscar por Nombre de Cliente
            $query->where('clientes.nombre', 'like', "%$buscar%");
        } else {
            // Buscar por N° de Contrato
            $query->where('extractos.idcontrato', $buscar);
        }
    }

    $ajustes = $query->orderByDesc('extractos.fecha')
        ->orderByDesc('extractos.id')
        ->paginate(50)
        ->withQueryString();

    return view('ajustes.index', compact('ajustes', 'buscar', 'buscax', 'tipo_ajuste'));
}

    // ── Ver detalle ──────────────────────────────────────────────────────────
    public function show(int $id)
    {
        $ajuste = DB::table('extractos')
            ->whereIn('tipmov', [5, 6])
            ->where('id', $id)
            ->first();

        abort_if(! $ajuste, 404);

        $cliente  = DB::table('clientes')->where('id', $ajuste->idcliente)->first();
        $contrato = DB::table('contratos')->where('id', $ajuste->idcontrato)->first();
        $tipore   = $ajuste->tipmov == 5 ? 'Cargo' : 'Abono';

        return view('ajustes.show', compact('ajuste', 'cliente', 'contrato', 'tipore'));
    }

    // ── Formulario nuevo ajuste ──────────────────────────────────────────────
    public function create()
    {
        $this->soloAdmin();

        $nuevoId = (DB::table('extractos')
            ->whereIn('tipmov', [5, 6])
            ->max('id') ?? 0) + 1;

        $hoy = FechaHelper::hoy();

        return view('ajustes.create', compact('nuevoId', 'hoy'));
    }

    // ── Guardar ajuste ───────────────────────────────────────────────────────
    public function store(Request $request)
    {
        $this->soloAdmin();

        $request->validate([
            'idajuste'      => 'required|integer',
            'cliente'       => 'required|integer',
            'contrato'      => 'required|integer',
            'tipoajuste'    => 'required|in:1,2',
            'monto'         => 'required|numeric|min:0.01',
            'observaciones' => 'required|string|min:3|max:200',
        ], [
            'cliente.required'       => 'Seleccione un cliente.',
            'contrato.required'      => 'Seleccione un contrato.',
            'tipoajuste.required'    => 'Seleccione el tipo de ajuste.',
            'monto.required'         => 'Ingrese el monto del ajuste.',
            'observaciones.required' => 'Las observaciones son obligatorias.',
        ]);

        $idajuste   = (int) $request->idajuste;
        $idcliente  = (int) $request->cliente;
        $idcontrato = (int) $request->contrato;
        $tipoajuste = (int) $request->tipoajuste;
        $monto      = (float) $request->monto;
        $fecha      = FechaHelper::localToBd($request->fecha);
        $fechaven   = $request->fechaven
                        ? FechaHelper::localToBd($request->fechaven)
                        : '0000-00-00';
        $observaciones = $request->observaciones;

        $existe = DB::table('extractos')
            ->where('id', $idajuste)
            ->whereIn('tipmov', [5, 6])
            ->exists();

        if ($existe) {
            return back()
                ->with('error', "El ajuste #$idajuste ya fue realizado anteriormente.")
                ->withInput();
        }

        $base = [
            'id'           => $idajuste,
            'fecha'        => $fecha,
            'numman'       => 0,
            'numcuo'       => 0,
            'numrec'       => 0,
            'tiprec'       => 0,
            'numaju'       => 0,
            'tipmon'       => 2,
            'idcontrato'   => $idcontrato,
            'idcliente'    => $idcliente,
            'cargo'        => $monto,
            'abono'        => 0,
            'abono2'       => 0,
            'abono3'       => 0,
            'saldo'        => 0,
            'tipocambio'   => 0,
            'anulado'      => 0,
            'titulo'       => $observaciones,
            'montosus'     => 0,
            'montobs'      => 0,
            'fechaanulado' => '0000-00-00',
            'idcobrador'   => 0,
            'idvendedor'   => 0,
            'respons'      => 'Sistema',
            'flag'         => 0,
            'numcomp'      => 0,
            'fechcomp'     => '0000-00-00',
            'clascomp'     => 0,
        ];

        if ($tipoajuste == 2) {
            // Abono
            DB::table('extractos')->insert(array_merge($base, [
                'tipmov'   => 6,
                'tipo'     => 2,
                'fechaven' => '0000-00-00',
            ]));
            SeguimientoHelper::registrar($idajuste, 1, 6);
            $this->distribuirAbonoEnCuotas($idajuste, $idcontrato, $idcliente, $monto);
        } else {
            // Cargo
            DB::table('extractos')->insert(array_merge($base, [
                'tipmov'   => 5,
                'tipo'     => 1,
                'fechaven' => $fechaven,
            ]));
            SeguimientoHelper::registrar($idajuste, 1, 13);
        }

        $this->actualizarEstadoLote($idcontrato, $idcliente);

        return redirect()->route('ajustes.show', $idajuste)
            ->with('success', "Ajuste #$idajuste guardado correctamente.");
    }

    // ── AJAX: contratos vigentes de un cliente ────────────────────────────────
    public function getContratosCliente(int $idcliente)
    {
        $contratos = DB::table('contratos')
            ->leftJoin('urbanizaciones', 'contratos.urbanizacion', '=', 'urbanizaciones.id')
            ->where('contratos.idcliente', $idcliente)
            ->where('contratos.anul', 0)
            ->select(
                'contratos.id as idcontrato',
                'contratos.manzano',
                'contratos.lote',
                'contratos.idlote',
                'urbanizaciones.nombre as nom_urb',
            )
            ->get();

        return response()->json($contratos);
    }


    // =========================================================================
    // REPORTES
    // =========================================================================

    // ── PDF ajuste individual ─────────────────────────────────────────────────
    // Llamado desde show.blade.php → route('ajustes.pdf', $ajuste->id)
    // Reemplaza: ajuste.php + pdf_ajuste.php del sistema legacy
    public function ajustePdf(int $id)
    {
        // ── Ajuste (extracto) ────────────────────────────────────────────────
        $ajuste = DB::table('extractos')
            ->whereIn('tipmov', [5, 6])
            ->where('id', $id)
            ->first();

        abort_if(! $ajuste, 404, 'Ajuste no encontrado.');

        $tipo     = $ajuste->tipmov;
        $tipLabel = $tipo == 5 ? 'CARGO' : 'ABONO';
        $tipoid   = $tipo == 5 ? 13 : 6;

        // ── Tipo de cambio a la fecha del ajuste ─────────────────────────────
        $tipocambio = DB::table('tipocambios')
            ->where('fecha', $ajuste->fecha)
            ->value('tc') ?? 0;

        // ── Usuario que registró el ajuste ───────────────────────────────────
        $seguim = DB::table('seguimiento')
            ->where('id', $id)
            ->where('tipomov', 1)
            ->where('tipoid', $tipoid)
            ->first();

        $nomUserRegistro = '';
        if ($seguim) {
            $uReg = DB::table('usuarios')->where('id', $seguim->usuario)->first();
            $nomUserRegistro = $uReg
                ? trim($uReg->nombre . ' ' . ($uReg->apellidos ?? ''))
                : '';
        }

        $uActual       = auth()->user();
        $nomUserActual = $uActual
            ? trim($uActual->nombre . ' ' . ($uActual->apellidos ?? ''))
            : '';

        // ── Cliente ──────────────────────────────────────────────────────────
        $cliente   = DB::table('clientes')->where('id', $ajuste->idcliente)->first();
        $nombrecli = $cliente
            ? trim(($cliente->apellido ?? '') . ' ' . $cliente->nombre)
            : '';

        // ── Contrato ─────────────────────────────────────────────────────────
        $contrato = DB::table('contratos')->where('id', $ajuste->idcontrato)->first();
        abort_if(! $contrato, 404, 'Contrato no encontrado.');

        // ── Urbanización y distrito ───────────────────────────────────────────
        $nomUrb  = DB::table('urbanizaciones')->where('id', $contrato->urbanizacion)->value('nombre') ?? '';
        $nomDist = DB::table('distritos')->where('id', $contrato->distrito)->value('nombre') ?? '';

        // ── Monto y literal ──────────────────────────────────────────────────
        $cargoFormateado = number_format((float) $ajuste->cargo, 2);
        $literal         = self::numALetras((float) $ajuste->cargo) . ' DOLARES';
        $literal         = ucwords(strtolower($literal));

        // Título del ajuste en fragmentos de 40 chars (igual que legacy)
        $titulo = $ajuste->titulo ?? '';
        $texto2 = substr($titulo,  0, 40);
        $texto3 = substr($titulo, 40, 40);
        $texto4 = substr($titulo, 80, 40);

        // ── Fechas formateadas ────────────────────────────────────────────────
        $fechaAjuste   = FechaHelper::bdToLocal($ajuste->fecha);
        $fechaContrato = FechaHelper::bdToLocal($contrato->fecha ?? '');
        $fechaVen      = ($ajuste->fechaven && $ajuste->fechaven !== '0000-00-00')
                            ? FechaHelper::bdToLocal($ajuste->fechaven)
                            : '';

        $datos = (object) [
            'id'             => $ajuste->id,
            'fechaAjuste'    => $fechaAjuste,
            'fechaVen'       => $fechaVen,
            'tip'            => $tipLabel,
            'idcontrato'     => $ajuste->idcontrato,
            'fechaContrato'  => $fechaContrato,
            'urbanizacion'   => $nomUrb,
            'distrito'       => $nomDist,
            'idcliente'      => $ajuste->idcliente,
            'nombrecli'      => $nombrecli,
            'manzano'        => $contrato->manzano,
            'lote'           => $contrato->lote,
            'superficie'     => $contrato->superficie,
            'bolivianos'     => '0.00',
            'cargo'          => $cargoFormateado,
            'tipocambio'     => $tipocambio,
            'literal'        => $literal,
            'observacion' => $ajuste->titulo ?? '',
            // 'texto2'         => $texto2,
            // 'texto3'         => $texto3,
            // 'texto4'         => $texto4,
            'nomUserRegistro'=> $nomUserRegistro,
            'nomUserActual'  => $nomUserActual,
        ];

        $pdf = Pdf::loadView('ajustes.ajuste_pdf', compact('datos'))
            ->setPaper('letter', 'portrait');

        return $pdf->stream("ajuste-{$id}.pdf");
    }

    // ── Formulario: ajustes realizados (listado por rango) ────────────────────
    // Reemplaza: el form que invocaba ajustesrealizados.php
    public function realizadosForm()
    {
        return view('ajustes.realizados_form');
    }

    // ── PDF: ajustes realizados ───────────────────────────────────────────────
    // Reemplaza: ajustesrealizados.php + pdf_ajustesrealizados.php
    public function realizadosPdf(Request $request)
    {
        $request->validate([
            'fechaini' => 'required|date',
            'fechafin' => 'required|date|after_or_equal:fechaini',
            'tipmov'   => 'required|in:5,6,0',
        ]);

        $fechaini = $request->fechaini;
        $fechafin = $request->fechafin;
        $tipmov   = (int) $request->tipmov;

        $query = DB::table('extractos')
            ->where('anulado', 0)
            ->whereBetween('fecha', [$fechaini, $fechafin]);

        $tipmov === 0
            ? $query->whereIn('tipmov', [5, 6])
            : $query->where('tipmov', $tipmov);

        $extractos = $query->orderBy('fecha')->get();

        // Enriquecer con nombre de cliente
        $ajustes = $extractos->map(function ($ext) {
            $cliente = DB::table('clientes')->where('id', $ext->idcliente)->first();
            return (object) [
                'id'         => $ext->id,
                'fecha'      => $ext->fecha,
                'idcontrato' => $ext->idcontrato,
                'idcliente'  => $ext->idcliente,
                'nomcli'     => $cliente
                    ? trim(($cliente->apellido ?? '') . ' ' . $cliente->nombre)
                    : '',
                'monto'      => number_format((float) $ext->cargo, 2),
                'tipo'       => $ext->tipmov == 5 ? 'Cargo' : 'Abono',
            ];
        });

        $tipoLabel = match($tipmov) {
            5       => 'Cargos',
            6       => 'Abonos',
            default => 'Cargos y Abonos',
        };

        $pdf = Pdf::loadView('ajustes.realizados_pdf', [
            'ajustes'   => $ajustes,
            'fechaini'  => FechaHelper::bdToLocal($fechaini),
            'fechafin'  => FechaHelper::bdToLocal($fechafin),
            'tipoLabel' => $tipoLabel,
        ])->setPaper('letter', 'portrait');

        return $pdf->download("ajustes-realizados-{$fechaini}-{$fechafin}.pdf");
    }

    // ── Formulario: ajustes por fecha (vista HTML) ────────────────────────────
    // Reemplaza: ajustesxfecha.php
    public function porFechaForm()
    {
        return view('ajustes.porfecha_form');
    }

    public function porFecha(Request $request)
    {
        $request->validate([
            'fechaini' => 'required|date',
            'fechafin' => 'required|date|after_or_equal:fechaini',
        ]);

        $fechaini = $request->fechaini;
        $fechafin = $request->fechafin;

        $extractos = DB::table('extractos')
            ->where('anulado', 0)
            ->whereIn('tipmov', [5, 6])
            ->whereBetween('fecha', [$fechaini, $fechafin])
            ->orderBy('tipmov')
            ->orderBy('fecha')
            ->get();

        $ajustes = $extractos->map(function ($ext) {
            $contrato = DB::table('contratos')->where('id', $ext->idcontrato)->first();
            $cliente  = DB::table('clientes')->where('id', $ext->idcliente)->value('nombre') ?? '';

            $seguim  = DB::table('seguimiento')
                ->where('id', $ext->id)
                ->where('tipomov', 1)
                ->whereIn('tipoid', [6, 13])
                ->first();

            $nomUser = $seguim
                ? DB::table('usuarios')->where('id', $seguim->usuario)->value('nombre') ?? ''
                : '';

            return (object) [
                'id'         => $ext->id,
                'fecha'      => $ext->fecha,
                'idcontrato' => $ext->idcontrato,
                'distrito'   => $contrato->distrito   ?? '',
                'manzano'    => $contrato->manzano    ?? '',
                'lote'       => $contrato->lote       ?? '',
                'superficie' => $contrato->superficie ?? '',
                'cliente'    => $cliente,
                'cargo'      => number_format((float) $ext->cargo, 2),
                'tipo'       => $ext->tipmov == 5 ? 'Cargo' : 'Abono',
                'titulo'     => $ext->titulo ?? '',
                'nomuser'    => $nomUser,
            ];
        });

        return view('ajustes.porfecha', compact('ajustes', 'fechaini', 'fechafin'));
    }


    private static function numALetras(float $numero): string
    {
        $entero   = (int) $numero;
        $decimals = (int) round(($numero - $entero) * 100);

        $unidades = ['','UNO','DOS','TRES','CUATRO','CINCO','SEIS','SIETE','OCHO','NUEVE',
                     'DIEZ','ONCE','DOCE','TRECE','CATORCE','QUINCE','DIECISÉIS',
                     'DIECISIETE','DIECIOCHO','DIECINUEVE'];
        $decenas  = ['','DIEZ','VEINTE','TREINTA','CUARENTA','CINCUENTA',
                     'SESENTA','SETENTA','OCHENTA','NOVENTA'];
        $centenas = ['','CIENTO','DOSCIENTOS','TRESCIENTOS','CUATROCIENTOS','QUINIENTOS',
                     'SEISCIENTOS','SETECIENTOS','OCHOCIENTOS','NOVECIENTOS'];

        $conv = function (int $n) use ($unidades, $decenas, $centenas, &$conv): string {
            if ($n === 0)   return 'CERO';
            if ($n === 100) return 'CIEN';
            if ($n < 20)    return $unidades[$n];
            if ($n < 100) {
                $d = intdiv($n, 10);
                $u = $n % 10;
                return $decenas[$d] . ($u ? ' Y ' . $unidades[$u] : '');
            }
            if ($n < 1000) {
                $c = intdiv($n, 100);
                $r = $n % 100;
                return $centenas[$c] . ($r ? ' ' . $conv($r) : '');
            }
            $miles = intdiv($n, 1000);
            $r     = $n % 1000;
            $pref  = $miles === 1 ? 'MIL' : $conv($miles) . ' MIL';
            return $pref . ($r ? ' ' . $conv($r) : '');
        };

        return $conv($entero) . ' ' . str_pad($decimals, 2, '0', STR_PAD_LEFT) . '/100';
    }

    private function distribuirAbonoEnCuotas(
        int $idAjuste, int $idcontrato, int $idcliente, float $pag
    ): void {
        $cuotas = DB::table('extractos')
            ->where('idcontrato', $idcontrato)
            ->where('idcliente', $idcliente)
            ->where('tipmov', 1)
            ->where('anulado', '!=', 1)
            ->orderBy('numcuo')
            ->get(['id', 'numcuo', 'cargo', 'abono']);

        if ($cuotas->isEmpty() || $pag <= 0) {
            return;
        }

        foreach ($cuotas as $cuota) {
            if ($pag <= 0) break;

            $resta = $cuota->cargo - $cuota->abono;
            if ($resta <= 0) continue;

            if ($pag >= $resta) {
                DB::table('extractos')
                    ->where('id', $cuota->id)
                    ->update(['numrec' => $idAjuste, 'abono' => $cuota->cargo]);
                $pag -= $resta;
            } else {
                DB::table('extractos')
                    ->where('id', $cuota->id)
                    ->update(['numrec' => $idAjuste, 'abono' => $cuota->abono + $pag]);
                $pag = 0;
            }
        }
    }

    private function actualizarEstadoLote(int $idcontrato, int $idcliente): void
    {
        $pendientes = DB::table('extractos')
            ->where('idcontrato', $idcontrato)
            ->where('idcliente', $idcliente)
            ->whereIn('tipmov', [1, 5])
            ->whereColumn('cargo', '!=', 'abono')
            ->where('anulado', 0)
            ->count();

        $idlote = DB::table('contratos')->where('id', $idcontrato)->value('idlote');
        if (! $idlote) return;

        DB::table('lotes')
            ->where('id', $idlote)
            ->update(['iteest' => $pendientes === 0 ? 4 : 3]);
    }

    private function soloAdmin(): void
    {
        if (auth()->user()->tipo != 1) {
            abort(403, 'Solo el administrador puede crear ajustes.');
        }
    }
}