<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\InstitucionPadre;
use App\Support\HistorialLogger;
use Illuminate\Http\Request;
use OpenSpout\Common\Entity\Row;
use OpenSpout\Common\Entity\Style\Color;
use OpenSpout\Common\Entity\Style\Style;
use OpenSpout\Writer\XLSX\Writer as XLSXWriter;

class InstitucionPadreController extends Controller
{
    public function index(Request $request)
    {
        $query = InstitucionPadre::query()
            ->select(['id_institucion_padre', 'nombre', 'descripcion', 'estado', 'fecha_creacion', 'fecha_actualizacion'])
            ->withCount('organismos');

        if ($request->filled('estado')) {
            $query->where('estado', $request->string('estado'));
        }

        if ($request->filled('q')) {
            $q = trim((string) $request->string('q'));
            if ($q !== '') {
                $query->where('nombre', 'like', '%'.$q.'%');
            }
        }

        $perPage = (int) $request->integer('per_page', 20);
        if ($perPage < 1) {
            $perPage = 1;
        }
        if ($perPage > 100) {
            $perPage = 100;
        }

        $paginator = $query->orderBy('nombre')->paginate($perPage);

        return response()->json([
            'data' => $paginator->items(),
            'meta' => [
                'current_page' => $paginator->currentPage(),
                'per_page' => $paginator->perPage(),
                'last_page' => $paginator->lastPage(),
                'total' => $paginator->total(),
            ],
        ]);
    }

    public function options()
    {
        $rows = InstitucionPadre::query()
            ->select(['id_institucion_padre', 'nombre'])
            ->where('estado', 'activo')
            ->orderBy('nombre')
            ->limit(500)
            ->get();

        return response()->json(['data' => $rows]);
    }

    public function store(Request $request)
    {
        $data = $request->validate([
            'nombre' => ['required', 'string', 'max:200', 'unique:instituciones_padre,nombre'],
            'descripcion' => ['nullable', 'string'],
            'estado' => ['nullable', 'in:activo,inactivo'],
        ]);

        $data['nombre'] = trim((string) $data['nombre']);
        if (array_key_exists('descripcion', $data) && is_string($data['descripcion'])) {
            $data['descripcion'] = trim($data['descripcion']);
            if ($data['descripcion'] === '') {
                $data['descripcion'] = null;
            }
        }

        $institucion = InstitucionPadre::create($data);

        HistorialLogger::log(
            $request->user()?->getKey(),
            'institucion_creada',
            'instituciones-padre',
            (string) $institucion->getKey(),
            'Creación de institución',
            null,
            $institucion->toArray()
        );

        return response()->json($institucion->loadCount('organismos'), 201);
    }

    public function show(InstitucionPadre $institucionPadre)
    {
        return response()->json($institucionPadre->loadCount('organismos'));
    }

    public function update(Request $request, InstitucionPadre $institucionPadre)
    {
        $data = $request->validate([
            'nombre' => ['sometimes', 'required', 'string', 'max:200', 'unique:instituciones_padre,nombre,'.$institucionPadre->getKey().',id_institucion_padre'],
            'descripcion' => ['nullable', 'string'],
            'estado' => ['sometimes', 'required', 'in:activo,inactivo'],
        ]);

        if (array_key_exists('nombre', $data)) {
            $data['nombre'] = trim((string) $data['nombre']);
        }

        if (array_key_exists('descripcion', $data) && is_string($data['descripcion'])) {
            $data['descripcion'] = trim($data['descripcion']);
            if ($data['descripcion'] === '') {
                $data['descripcion'] = null;
            }
        }

        $antes = $institucionPadre->loadCount('organismos')->toArray();

        $institucionPadre->fill($data)->save();

        $despues = $institucionPadre->loadCount('organismos')->toArray();

        HistorialLogger::log(
            $request->user()?->getKey(),
            'institucion_actualizada',
            'instituciones-padre',
            (string) $institucionPadre->getKey(),
            'Actualización de institución',
            $antes,
            $despues
        );

        return response()->json($institucionPadre->loadCount('organismos'));
    }

    public function destroy(Request $request, InstitucionPadre $institucionPadre)
    {
        if ($institucionPadre->estado === 'inactivo') {
            return response()->json($institucionPadre->loadCount('organismos'));
        }

        $antes = $institucionPadre->loadCount('organismos')->toArray();

        $institucionPadre->forceFill(['estado' => 'inactivo'])->save();

        $despues = $institucionPadre->loadCount('organismos')->toArray();

        HistorialLogger::log(
            $request->user()?->getKey(),
            'institucion_inactivada',
            'instituciones-padre',
            (string) $institucionPadre->getKey(),
            'Inactivación de institución',
            $antes,
            $despues
        );

        return response()->json($institucionPadre->loadCount('organismos'));
    }

    public function export(Request $request)
    {
        $query = InstitucionPadre::query()->withCount('organismos');

        if ($request->filled('estado')) {
            $query->where('estado', $request->string('estado'));
        }

        if ($request->filled('q')) {
            $q = trim((string) $request->string('q'));
            if ($q !== '') {
                $query->where('nombre', 'like', '%'.$q.'%');
            }
        }

        $fileName = 'instituciones.xlsx';

        return response()->streamDownload(function () use ($query) {
            $writer = new XLSXWriter();
            $writer->openToFile('php://output');
            $sheet = $writer->getCurrentSheet();
            $sheet->setName('Instituciones');

            $headerStyle = (new Style())->setFontBold();
            $writer->addRow(Row::fromValues([
                'Institución',
                'Descripción',
                'Estado',
                'Organismos',
            ], $headerStyle));

            $rowStyleEven = (new Style())->setBackgroundColor(Color::WHITE);
            $rowStyleOdd = (new Style())->setBackgroundColor(Color::rgb(243, 251, 255));
            $rowIndex = 0;

            $query->orderBy('nombre')->chunk(500, function ($rows) use ($writer, $rowStyleEven, $rowStyleOdd, &$rowIndex) {
                foreach ($rows as $row) {
                    $rowIndex++;
                    $style = $rowIndex % 2 === 0 ? $rowStyleEven : $rowStyleOdd;
                    $writer->addRow(Row::fromValues([
                        (string) ($row->nombre ?? ''),
                        (string) ($row->descripcion ?? ''),
                        (string) ($row->estado ?? ''),
                        (int) ($row->organismos_count ?? 0),
                    ], $style));
                }
            });

            $sheet->setColumnWidth(30, 1);
            $sheet->setColumnWidth(40, 2);
            $sheet->setColumnWidth(14, 3);
            $sheet->setColumnWidth(16, 4);

            $writer->close();
        }, $fileName, [
            'Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        ]);
    }
}

