<?php

namespace App\Services\Payroll;

use App\Models\EmployeePayroll;
use App\Models\PayrollCycle;
use Symfony\Component\HttpFoundation\StreamedResponse;

class PayrollBankExportService
{
    /**
     * Standard NEFT-style CSV for Indian bank uploads (beneficiary name, account, IFSC, amount, reference).
     *
     * @return list<array{employee_number: string, name: string, account_holder: string, account_number: string, ifsc: string, bank_name: string, net_amount: float, reference: string}>
     */
    public function rowsForCycle(PayrollCycle $cycle): array
    {
        $cycle->loadMissing(['employeePayrolls.user']);

        $rows = [];
        foreach ($cycle->employeePayrolls as $ep) {
            if ((float) $ep->net_monthly <= 0) {
                continue;
            }

            $user = $ep->user;
            if (! $user) {
                continue;
            }

            $accountNumber = trim((string) ($user->account_number ?? ''));
            $ifsc = trim((string) ($user->ifsc_code ?? ''));
            if ($accountNumber === '' || $ifsc === '') {
                continue;
            }

            $rows[] = [
                'employee_number' => (string) ($user->employee_number ?: $user->id),
                'name' => (string) $user->name,
                'account_holder' => (string) ($user->account_holder_name ?: $user->name),
                'account_number' => $accountNumber,
                'ifsc' => strtoupper($ifsc),
                'bank_name' => (string) ($user->bank_name ?? ''),
                'net_amount' => round((float) $ep->net_monthly, 2),
                'reference' => sprintf('SAL-%04d%02d-%s', $cycle->year, $cycle->month, $user->employee_number ?: $user->id),
            ];
        }

        return $rows;
    }

    public function missingBankDetails(PayrollCycle $cycle): array
    {
        $missing = [];
        foreach ($cycle->employeePayrolls as $ep) {
            if ((float) $ep->net_monthly <= 0) {
                continue;
            }
            $user = $ep->user;
            if (! $user) {
                continue;
            }
            if (empty($user->account_number) || empty($user->ifsc_code)) {
                $missing[] = $user->name;
            }
        }

        return $missing;
    }

    public function downloadCsv(PayrollCycle $cycle): StreamedResponse
    {
        $rows = $this->rowsForCycle($cycle);
        $filename = sprintf('neft-payroll-%04d-%02d.csv', $cycle->year, $cycle->month);

        return response()->streamDownload(function () use ($rows, $cycle) {
            $handle = fopen('php://output', 'w');
            fputcsv($handle, [
                'Employee ID',
                'Employee Name',
                'Beneficiary Name',
                'Account Number',
                'IFSC',
                'Bank Name',
                'Net Amount',
                'Payment Reference',
                'Payroll Month',
            ]);

            foreach ($rows as $row) {
                fputcsv($handle, [
                    $row['employee_number'],
                    $row['name'],
                    $row['account_holder'],
                    $row['account_number'],
                    $row['ifsc'],
                    $row['bank_name'],
                    number_format($row['net_amount'], 2, '.', ''),
                    $row['reference'],
                    sprintf('%04d-%02d', $cycle->year, $cycle->month),
                ]);
            }

            fclose($handle);
        }, $filename, ['Content-Type' => 'text/csv']);
    }

    public function downloadPayrollSummaryCsv(PayrollCycle $cycle): StreamedResponse
    {
        $cycle->loadMissing(['employeePayrolls.user.department', 'employeePayrolls.components']);
        $filename = sprintf('payroll-%04d-%02d.csv', $cycle->year, $cycle->month);

        return response()->streamDownload(function () use ($cycle) {
            $handle = fopen('php://output', 'w');
            fputcsv($handle, ['Employee ID', 'Name', 'Department', 'Gross', 'Deductions', 'Net Salary', 'Status']);

            foreach ($cycle->employeePayrolls as $ep) {
                $user = $ep->user;
                $gross = (float) ($ep->gross_monthly ?? 0);
                $net = (float) ($ep->net_monthly ?? 0);
                $deductions = (float) ($ep->total_deductions ?? max(0, $gross - $net));
                $empId = $user?->employee_number ?? 'EMP' . str_pad((string) ($ep->user_id ?? 0), 3, '0', STR_PAD_LEFT);

                fputcsv($handle, [
                    $empId,
                    $user?->name ?? '—',
                    $user?->department?->name ?? '—',
                    number_format($gross, 2),
                    number_format($deductions, 2),
                    number_format($net, 2),
                    $ep->status ?? 'pending',
                ]);
            }

            fclose($handle);
        }, $filename, ['Content-Type' => 'text/csv']);
    }
}
