<?php

namespace App\Http\Controllers\Backend\Payroll;

use App\Exports\BankFileExport;
use App\Http\Controllers\Controller;
use App\Models\Finance\CompanyBankAccount;
use Barryvdh\DomPDF\Facade\Pdf;
use Brian2694\Toastr\Facades\Toastr;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Facades\Excel;

/**
 * Punto 2 — Generación de archivo para banco.
 *
 * Selecciona una quincena calculada, una cuenta empresarial (de dónde sale
 * el dinero) y un banco destino (en qué banco cobran los empleados) y emite
 * un PDF o Excel con la nómina lista para enviar al banco.
 */
class BankFileController extends Controller
{
    /**
     * Pantalla de generación del archivo para banco.
     */
    public function index()
    {
        $companyId = auth()->user()->company_id ?? 1;

        $accounts = CompanyBankAccount::forCurrentCompany()
            ->where('status_id', 1)
            ->orderBy('bank_name')
            ->get();

        $banks = DB::table('bank_accounts')
            ->where('company_id', $companyId)
            ->whereNotNull('bank_name')
            ->where('bank_name', '!=', '')
            ->distinct()
            ->orderBy('bank_name')
            ->pluck('bank_name');

        $dates = DB::table('salary_generates')
            ->where('company_id', $companyId)
            ->where('is_calculated', 1)
            ->distinct()
            ->orderBy('date', 'desc')
            ->pluck('date');

        $data = [
            'title' => 'Archivo para Banco',
        ];

        return view('backend.payroll.bank_file.index', compact('accounts', 'banks', 'dates', 'data'));
    }

    /**
     * Generar archivo PDF o Excel.
     */
    public function generate(Request $request)
    {
        $validated = $request->validate([
            'date'                     => 'required|date',
            'company_bank_account_id'  => 'required|integer|exists:company_bank_accounts,id',
            'bank_name'                => 'required|string|max:255',
            'format'                   => 'nullable|string|in:pdf,excel',
        ]);

        $companyId = auth()->user()->company_id ?? 1;
        $date      = $validated['date'];
        $bankName  = $validated['bank_name'];
        $format    = $validated['format'] ?? 'pdf';

        try {
            $companyBankAccount = CompanyBankAccount::forCurrentCompany()
                ->findOrFail($validated['company_bank_account_id']);

            $company = DB::table('companies')->where('id', $companyId)->first();

            $data = DB::table('salary_generates as sg')
                ->join('users as u', 'u.id', '=', 'sg.user_id')
                ->leftJoin('bank_accounts as ba', 'ba.user_id', '=', 'u.id')
                ->where('sg.date', $date)
                ->where('sg.company_id', $companyId)
                ->where('sg.is_calculated', 1)
                ->where('ba.bank_name', $bankName)
                ->select(
                    'u.id as user_id',
                    'u.name as employee_name',
                    'ba.account_number',
                    'ba.bank_name',
                    DB::raw('COALESCE(sg.net_salary, sg.amount) as salary')
                )
                ->orderBy('u.name')
                ->get();

            if ($data->isEmpty()) {
                Toastr::warning('No hay empleados con planilla calculada para esa fecha y banco.', 'Sin datos');
                return redirect()->route('hrm.payroll.bank_file.index');
            }

            if ($format === 'excel') {
                $filename = 'archivo_banco_' . str_replace(' ', '_', strtolower($bankName)) . '_' . $date . '.xlsx';
                return Excel::download(
                    new BankFileExport($data, $companyBankAccount, $date, $company, $bankName),
                    $filename
                );
            }

            // PDF (default)
            $filename = 'archivo_banco_' . str_replace(' ', '_', strtolower($bankName)) . '_' . $date . '.pdf';

            $pdf = Pdf::loadView('backend.payroll.bank_file.pdf', [
                'data'               => $data,
                'companyBankAccount' => $companyBankAccount,
                'date'               => $date,
                'company'            => $company,
                'bankName'           => $bankName,
                'range'              => $this->computeFortnightRange($date),
            ])->setPaper('letter', 'portrait');

            return $pdf->download($filename);
        } catch (\Throwable $th) {
            Toastr::error('Error al generar el archivo: ' . $th->getMessage(), 'Error');
            return redirect()->route('hrm.payroll.bank_file.index');
        }
    }

    /**
     * Convertir una fecha de planilla en su rango quincenal.
     * - día <= 15 → 1 al 15 del mes
     * - día > 15  → 16 al último día del mes
     *
     * Devuelve ['start' => '1', 'end' => '15', 'month' => 'Marzo', 'year' => 2026, 'label' => '01 al 15 de Marzo de 2026']
     */
    private function computeFortnightRange(string $date): array
    {
        $mesesEs = [
            1 => 'Enero', 2 => 'Febrero', 3 => 'Marzo', 4 => 'Abril',
            5 => 'Mayo', 6 => 'Junio', 7 => 'Julio', 8 => 'Agosto',
            9 => 'Septiembre', 10 => 'Octubre', 11 => 'Noviembre', 12 => 'Diciembre',
        ];

        $d = Carbon::parse($date);
        $day = (int) $d->day;
        $month = $mesesEs[(int) $d->month] ?? $d->format('F');
        $year = $d->year;

        if ($day <= 15) {
            $start = 1;
            $end = 15;
        } else {
            $start = 16;
            $end = (int) $d->copy()->endOfMonth()->day;
        }

        $label = str_pad((string) $start, 2, '0', STR_PAD_LEFT)
            . ' al '
            . str_pad((string) $end, 2, '0', STR_PAD_LEFT)
            . ' de ' . $month . ' de ' . $year;

        return compact('start', 'end', 'month', 'year', 'label');
    }
}
