<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Helpers\FechaHelper;
use App\Helpers\SeguimientoHelper;

/**
 * DevolucionController
 * Equivalente al módulo devoluciones/ del sistema original
 *
 * Archivos originales migrados:
 *   index.php       → index()
 *   rejilla.php     → index() con paginación
 *   ver_contrato.php → show()
 *   anular_contrato.php → destroy()
 */
class DevolucionController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }

    // ── Listado de contratos vigentes para devolver ──────────────────────────
    public function index(Request $request)
    {
        $buscar = $request->input('buscar', '');

        $contratos = DB::table('contratos')
            ->leftJoin('clientes',       'contratos.idcliente',   '=', 'clientes.id')
            ->leftJoin('urbanizaciones', 'contratos.urbanizacion','=', 'urbanizaciones.id')
            ->leftJoin('distritos',      'contratos.distrito',    '=', 'distritos.id')
            ->where('contratos.anul', 0) // solo vigentes
            ->when($buscar, fn($q) => $q->where('contratos.id', $buscar))
            ->select(
                'contratos.id',
                'contratos.numman',
                'contratos.fecha',
                'contratos.urbanizacion',
                'contratos.distrito',
                'contratos.manzano',
                'contratos.lote',
                'contratos.idcliente',
                'clientes.nombre       as nom_cliente',
                'urbanizaciones.nombre as nom_urb',
                'distritos.nomcorto    as nom_dis',
            )
            ->orderBy('contratos.id', 'desc')
            ->paginate(30)
            ->withQueryString();

        return view('devoluciones.index', compact('contratos', 'buscar'));
    }

    // ── Ver detalle del contrato antes de anular ─────────────────────────────
    public function show($id)
    {
        $this->soloAdmin();

        $contrato = DB::table('contratos')->where('id', $id)->first();

        if (!$contrato) abort(404);

        $cliente = DB::table('clientes')
            ->where('id', $contrato->idcliente)
            ->first();

        $codeudores = DB::table('codeudores')
            ->join('clientes', 'codeudores.idcliente', '=', 'clientes.id')
            ->where('codeudores.idcontrato', $id)
            ->select('clientes.nombre', 'clientes.ci')
            ->get();

        $urbanizacion = DB::table('urbanizaciones')
            ->where('id', $contrato->urbanizacion)->first();

        $distrito = DB::table('distritos')
            ->where('id', $contrato->distrito)->first();

        $vendedor = DB::table('vendedores')
            ->where('id', $contrato->idvendedor)->first();

        return view('devoluciones.show', compact(
            'contrato', 'cliente', 'codeudores',
            'urbanizacion', 'distrito', 'vendedor'
        ));
    }

    // ── Anular contrato — equivalente a anular_contrato.php ─────────────────
    public function destroy(Request $request, $id)
    {
        $this->soloAdmin();

        $request->validate([
            'obsanul' => 'required|string|min:5|max:200',
        ], [
            'obsanul.required' => 'Ingrese las observaciones de la anulación.',
            'obsanul.min'      => 'Las observaciones deben tener al menos 5 caracteres.',
        ]);

        $now          = now('America/La_Paz');
        $hoy          = $now->format('Y-m-d');
        $obsanul      = $request->obsanul;
        $usuario      = auth()->user()->nombre . ' ' . auth()->user()->apellidos;

        // ── 1. Obtener datos del contrato ────────────────────────────────────
        $contrato = DB::table('contratos')->where('id', $id)->first();

        if (!$contrato || $contrato->anul == 1) {
            return back()->with('error', 'El contrato ya está anulado o no existe.');
        }

        $idlote    = $contrato->idlote;
        $idcliente = $contrato->idcliente;

        // ── 2. Marcar contrato como anulado ──────────────────────────────────
        DB::table('contratos')
            ->where('id', $id)
            ->update([
                'actudat'  => auth()->id(),
                'fechacomp'=> $hoy,
                'anul'     => 1,
                'obsanul'  => $obsanul,
            ]);

        // ── 3. Seguimiento ───────────────────────────────────────────────────
        SeguimientoHelper::bajaContrato($id);

        // ── 4. Cambiar estado del lote a Disponible (iteest = 1) ─────────────
        DB::table('lotes')
            ->where('id', $idlote)
            ->update(['iteest' => 1]);

        // ── 5. Anular extractos del contrato ─────────────────────────────────
        DB::table('extractos')
            ->where('idcontrato', $id)
            ->where('idcliente', $idcliente)
            ->update(['anulado' => 1]);

        // ── 6. Mover recibos a tabla anulados y eliminarlos ──────────────────
        $this->procesarRecibos($id, $idcliente, $hoy, $usuario);

        // ── 7. Anular trámites asociados al lote/cliente ─────────────────────
        $tramite = DB::table('tramites')
            ->where('idlote', $idlote)
            ->where('idcliente', $idcliente)
            ->first();

        if ($tramite) {
            $idTramite = $tramite->id;

            foreach (['tramites', 'transferencias', 'protocolos', 'planolotes', 'visados', 'minutas', 'derechosreales'] as $tabla) {
                try {
                    DB::table($tabla)
                        ->where('id', $idTramite)
                        ->update(['anul' => 1]);
                } catch (\Exception $e) {
                    // Tabla puede no existir o no tener el campo — ignorar
                }
            }
        }

        // ── 8. Anular notas de entrega ───────────────────────────────────────
        DB::table('notas')
            ->where('idlote', $idlote)
            ->where('idcliente', $idcliente)
            ->update(['anul' => 1]);

        return redirect()->route('devoluciones.index')
                         ->with('success', "Contrato #$id anulado correctamente. Lote #$idlote vuelve a estar disponible.");
    }

    // ── Helpers privados ─────────────────────────────────────────────────────

    /**
     * Mueve los recibos a la tabla anulados y los elimina de recibos/recibosmov
     * Equivalente al while en anular_contrato.php
     */
    private function procesarRecibos(int $idContrato, int $idCliente, string $hoy, string $usuario): void
    {
        $recibos = DB::table('recibosmov')
            ->where('idcontrato', $idContrato)
            ->where('idcliente', $idCliente)
            ->select('id')
            ->groupBy('id')
            ->get();

        if ($recibos->isEmpty()) return;

        $maxAnulado = DB::table('anulados')->max('id') ?? 0;

        foreach ($recibos as $rec) {
            $idRecibo = $rec->id;
            $recibo   = DB::table('recibos')->where('id', $idRecibo)->first();

            if (!$recibo) continue;

            $maxAnulado++;

            // Insertar en tabla anulados
            DB::table('anulados')->insert([
                'id'       => $maxAnulado,
                'fechanu'  => $hoy,
                'numrec'   => $idRecibo,
                'fecha'    => $recibo->fecha,
                'tiprec'   => $recibo->tiporecibo ?? '',
                'numnot'   => $idContrato,
                'idcliente'=> $recibo->idcliente,
                'tc'       => $recibo->tc ?? 0,
                'moncob'   => $recibo->montocob ?? 0,
                'moncod'   => $recibo->montocod ?? 0,
                'obs'      => $recibo->observaciones ?? '',
                'codcob'   => $recibo->idcobrador ?? 0,
                'respons'  => $usuario,
            ]);

            // Eliminar de recibos y recibosmov
            DB::table('recibos')->where('id', $idRecibo)->delete();
            DB::table('recibosmov')->where('id', $idRecibo)->delete();
        }
    }

    private function soloAdmin(): void
    {
        if (auth()->user()->tipo != 1) {
            abort(403, 'Privilegio de acceso denegado. Solo el administrador puede anular contratos.');
        }
    }
}