<?php

declare(strict_types=1);

namespace ApiModel\Tests\Integration\Http;

use ApiModel\Action\HrAction;
use ApiModel\Infrastructure\Persistence\Repositories\PdoEmployeeRepository;
use ApiModel\Infrastructure\Persistence\Repositories\PdoDepartmentRepository;
use ApiModel\Infrastructure\Persistence\Repositories\PdoPayrollRepository;
use ApiModel\Infrastructure\Persistence\Repositories\PdoLeaveRepository;
use ApiModel\Infrastructure\Persistence\Repositories\PdoJournalRepository;
use ApiModel\Infrastructure\Persistence\Repositories\PdoChartAccountRepository;
use ApiModel\Infrastructure\Persistence\Repositories\PdoCompanyRepository;
use ApiModel\Infrastructure\Persistence\Repositories\PdoBranchRepository;
use ApiModel\Infrastructure\Persistence\Repositories\PdoExchangeRateRepository;
use ApiModel\Infrastructure\Persistence\Repositories\PdoUserAccessRepository;
use ApiModel\Infrastructure\Persistence\Repositories\PdoProfileRepository;
use ApiModel\Middleware\CompanyContextMiddleware;
use ApiModel\Middleware\ApiErrorHandler;
use ApiModel\Route\HrRoutes;
use ApiModel\Service\EmployeeService;
use ApiModel\Service\PayrollService;
use ApiModel\Service\LeaveService;
use ApiModel\Service\JournalService;
use ApiModel\Service\OrganizationService;
use Firebase\JWT\JWT;
use PDO;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\ResponseInterface;
use Slim\App;
use Slim\Factory\AppFactory;
use Slim\Psr7\Factory\ServerRequestFactory;
use Slim\Psr7\Factory\StreamFactory;

final class HrRoutesTest extends TestCase
{
    private PDO $pdo;
    private App $app;
    private string $adminToken;

    private const ADMIN_USER_ID = '11111111-1111-1111-1111-111111111111';
    private const ADMIN_ROLE_ID = '33333333-3333-3333-3333-333333333333';
    private const COMPANY_ID = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa';
    private const BRANCH_ID = 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb';

    private const EXPENSE_ACCOUNT_ID = '51050000-0000-0000-0000-000000000001';
    private const BANK_ACCOUNT_ID = '11100000-0000-0000-0000-000000000002';
    private const DEDUCTIONS_ACCOUNT_ID = '21050000-0000-0000-0000-000000000003';

    protected function setUp(): void
    {
        parent::setUp();

        $this->pdo = new PDO('sqlite::memory:');
        $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

        $this->createSchema();
        $this->seedData();
        $this->configureEnv();

        $this->app = $this->buildApp();
        $this->adminToken = $this->issueToken(self::ADMIN_USER_ID, 'ADMINISTRADOR');
    }

    private function companyHeaders(): array
    {
        return [
            'Authorization' => 'Bearer ' . $this->adminToken,
            'X-Company-Id' => self::COMPANY_ID,
        ];
    }

    public function testDepartmentCrud(): void
    {
        // 1. List departments - initially empty
        $res = $this->request('GET', '/hr/departments', $this->companyHeaders());
        $this->assertSame(200, $res->getStatusCode());
        $this->assertCount(0, $this->decodeBody($res));

        // 2. Create department
        $payload = ['name' => 'Tecnologia'];
        $res = $this->jsonRequest('POST', '/hr/departments', $payload, $this->companyHeaders());
        $this->assertSame(200, $res->getStatusCode());
        $dept = $this->decodeBody($res);
        $this->assertArrayHasKey('id', $dept);
        $this->assertSame('Tecnologia', $dept['name']);

        // 3. Update department
        $payload = ['name' => 'Tecnologia Avanzada', 'is_active' => false];
        $res = $this->jsonRequest('PUT', '/hr/departments/' . $dept['id'], $payload, $this->companyHeaders());
        $this->assertSame(200, $res->getStatusCode());
        $deptUpdated = $this->decodeBody($res);
        $this->assertSame('Tecnologia Avanzada', $deptUpdated['name']);
        $this->assertFalse($deptUpdated['is_active']);

        // 4. Delete department
        $res = $this->request('DELETE', '/hr/departments/' . $dept['id'], $this->companyHeaders());
        $this->assertSame(200, $res->getStatusCode());

        // 5. Verify deleted
        $res = $this->request('GET', '/hr/departments', $this->companyHeaders());
        $this->assertCount(0, $this->decodeBody($res));
    }

    public function testEmployeeAndContractCrud(): void
    {
        // 1. Create Department for Employee
        $deptRes = $this->jsonRequest('POST', '/hr/departments', ['name' => 'Ventas'], $this->companyHeaders());
        $dept = $this->decodeBody($deptRes);

        // 2. Create Employee with Contract nested
        $payload = [
            'first_name' => 'Juan',
            'last_name' => 'Perez',
            'email' => 'juan.perez@example.com',
            'phone' => '5551234',
            'identification_number' => '12345678',
            'hiring_date' => '2026-01-01',
            'department_id' => $dept['id'],
            'contract' => [
                'contract_type' => 'indefinido',
                'start_date' => '2026-01-01',
                'base_salary' => 2500.0,
                'status' => 'active',
            ],
        ];

        $res = $this->jsonRequest('POST', '/hr/employees', $payload, $this->companyHeaders());
        $this->assertSame(200, $res->getStatusCode());
        $emp = $this->decodeBody($res);
        $this->assertArrayHasKey('id', $emp);
        $this->assertSame('Juan', $emp['first_name']);
        $this->assertEquals(2500.0, $emp['base_salary']);
        $this->assertSame('indefinido', $emp['contract_type']);

        // 3. Update Employee and salary
        $payload = [
            'first_name' => 'Juan Carlos',
            'last_name' => 'Perez Gomez',
            'email' => 'juan.perez@example.com',
            'identification_number' => '12345678',
            'hiring_date' => '2026-01-01',
            'department_id' => $dept['id'],
            'contract' => [
                'contract_type' => 'indefinido',
                'start_date' => '2026-01-01',
                'base_salary' => 3000.0,
                'status' => 'active',
            ],
        ];
        $res = $this->jsonRequest('PUT', '/hr/employees/' . $emp['id'], $payload, $this->companyHeaders());
        $this->assertSame(200, $res->getStatusCode());
        $empUpdated = $this->decodeBody($res);
        $this->assertSame('Juan Carlos', $empUpdated['first_name']);
        $this->assertEquals(3000.0, $empUpdated['base_salary']);

        // 4. List employees
        $res = $this->request('GET', '/hr/employees', $this->companyHeaders());
        $this->assertCount(1, $this->decodeBody($res));

        // 5. Delete employee
        $res = $this->request('DELETE', '/hr/employees/' . $emp['id'], $this->companyHeaders());
        $this->assertSame(200, $res->getStatusCode());
    }

    public function testLeaveCrud(): void
    {
        // 1. Create employee
        $payloadEmp = [
            'first_name' => 'Maria',
            'last_name' => 'Lopez',
            'email' => 'maria@example.com',
            'identification_number' => '87654321',
            'hiring_date' => '2026-01-01',
        ];
        $empRes = $this->jsonRequest('POST', '/hr/employees', $payloadEmp, $this->companyHeaders());
        $emp = $this->decodeBody($empRes);

        // 2. Create leave
        $payloadLeave = [
            'employee_id' => $emp['id'],
            'leave_type' => 'vacacion',
            'start_date' => '2026-07-01',
            'end_date' => '2026-07-15',
            'status' => 'pending',
            'notes' => 'Vacaciones anuales',
        ];
        $res = $this->jsonRequest('POST', '/hr/leaves', $payloadLeave, $this->companyHeaders());
        $this->assertSame(200, $res->getStatusCode());
        $leave = $this->decodeBody($res);
        $this->assertArrayHasKey('id', $leave);
        $this->assertSame('vacacion', $leave['leave_type']);

        // 3. Update leave status
        $payloadLeave['status'] = 'approved';
        $res = $this->jsonRequest('PUT', '/hr/leaves/' . $leave['id'], $payloadLeave, $this->companyHeaders());
        $this->assertSame(200, $res->getStatusCode());
        $leaveUpdated = $this->decodeBody($res);
        $this->assertSame('approved', $leaveUpdated['status']);

        // 4. Delete leave
        $res = $this->request('DELETE', '/hr/leaves/' . $leave['id'], $this->companyHeaders());
        $this->assertSame(200, $res->getStatusCode());
    }

    public function testPayrollLifecycleAndAccountingPosting(): void
    {
        // 1. Create employee with contract and base salary
        $payloadEmp = [
            'first_name' => 'Pedro',
            'last_name' => 'Ramirez',
            'email' => 'pedro@example.com',
            'identification_number' => '44444444',
            'hiring_date' => '2026-01-01',
            'contract' => [
                'contract_type' => 'indefinido',
                'start_date' => '2026-01-01',
                'base_salary' => 2000.0,
                'status' => 'active',
            ],
        ];
        $empRes = $this->jsonRequest('POST', '/hr/employees', $payloadEmp, $this->companyHeaders());
        $emp = $this->decodeBody($empRes);

        // 2. Generate payroll - should auto-load employee
        $payloadPayroll = [
            'name' => 'Nomina Junio 2026',
            'start_date' => '2026-06-01',
            'end_date' => '2026-06-30',
        ];
        $res = $this->jsonRequest('POST', '/hr/payrolls', $payloadPayroll, $this->companyHeaders());
        $this->assertSame(200, $res->getStatusCode());
        $payroll = $this->decodeBody($res);
        $this->assertArrayHasKey('id', $payroll);
        $this->assertSame('Nomina Junio 2026', $payroll['name']);
        $this->assertEquals(2000.0, $payroll['total_earnings']);
        $this->assertEquals(0.0, $payroll['total_deductions']);
        $this->assertEquals(2000.0, $payroll['total_net']);
        $this->assertCount(1, $payroll['lines']);

        // 3. Update payroll lines (add bonus and deductions)
        $payroll['lines'][0]['bonuses'] = 300.0;
        $payroll['lines'][0]['deductions'] = 150.0;
        $res = $this->jsonRequest('PUT', '/hr/payrolls/' . $payroll['id'], $payroll, $this->companyHeaders());
        $this->assertSame(200, $res->getStatusCode());
        $payrollUpdated = $this->decodeBody($res);
        $this->assertEquals(2300.0, $payrollUpdated['total_earnings']); // 2000 base + 300 bonus
        $this->assertEquals(150.0, $payrollUpdated['total_deductions']);
        $this->assertEquals(2150.0, $payrollUpdated['total_net']);

        // 4. Post Payroll to Accounting
        $postPayload = [
            'expense_account_id' => self::EXPENSE_ACCOUNT_ID,
            'bank_account_id' => self::BANK_ACCOUNT_ID,
            'deductions_account_id' => self::DEDUCTIONS_ACCOUNT_ID,
        ];
        $res = $this->jsonRequest('POST', "/hr/payrolls/{$payroll['id']}/post", $postPayload, $this->companyHeaders());
        $this->assertSame(200, $res->getStatusCode());
        $payrollPosted = $this->decodeBody($res);
        $this->assertSame('posted', $payrollPosted['status']);
        $this->assertNotNull($payrollPosted['journal_entry_id']);

        // 5. Verify journal entries and lines exist
        $stmt = $this->pdo->prepare('SELECT * FROM journal_entries WHERE id = ?');
        $stmt->execute([$payrollPosted['journal_entry_id']]);
        $je = $stmt->fetch();
        $this->assertNotFalse($je);
        $this->assertSame('posted', $je['status']);

        // 6. Verify journal lines:
        // Debit Expense: 2300.0
        // Credit Deductions: 150.0
        // Credit Bank: 2150.0
        $stmtLines = $this->pdo->prepare('SELECT chart_account_id, debit, credit FROM journal_lines WHERE journal_entry_id = ? ORDER BY line_order ASC');
        $stmtLines->execute([$je['id']]);
        $lines = $stmtLines->fetchAll();

        $this->assertCount(3, $lines);

        $this->assertSame(self::EXPENSE_ACCOUNT_ID, $lines[0]['chart_account_id']);
        $this->assertEquals(2300.0, $lines[0]['debit']);
        $this->assertEquals(0.0, $lines[0]['credit']);

        $this->assertSame(self::DEDUCTIONS_ACCOUNT_ID, $lines[1]['chart_account_id']);
        $this->assertEquals(0.0, $lines[1]['debit']);
        $this->assertEquals(150.0, $lines[1]['credit']);

        $this->assertSame(self::BANK_ACCOUNT_ID, $lines[2]['chart_account_id']);
        $this->assertEquals(0.0, $lines[2]['debit']);
        $this->assertEquals(2150.0, $lines[2]['credit']);
    }

    private function buildApp(): App
    {
        $app = AppFactory::create();

        $orgRepo = new PdoCompanyRepository($this->pdo);
        $branchRepo = new PdoBranchRepository($this->pdo);
        $uaRepo = new PdoUserAccessRepository($this->pdo);
        $profRepo = new PdoProfileRepository($this->pdo);
        $orgService = new OrganizationService($orgRepo, $branchRepo, $uaRepo, $profRepo);
        
        $companyMiddleware = new CompanyContextMiddleware($orgService);

        $empRepo = new PdoEmployeeRepository($this->pdo);
        $deptRepo = new PdoDepartmentRepository($this->pdo);
        $payrollRepo = new PdoPayrollRepository($this->pdo);
        $leaveRepo = new PdoLeaveRepository($this->pdo);

        $journalRepo = new PdoJournalRepository($this->pdo);
        $chartAccountRepo = new PdoChartAccountRepository($this->pdo);
        $exchangeRateRepo = new PdoExchangeRateRepository($this->pdo);

        $journalService = new JournalService($journalRepo, $chartAccountRepo, $orgRepo, $branchRepo, $exchangeRateRepo);

        $employeeService = new EmployeeService($empRepo, $deptRepo);
        $payrollService = new PayrollService($payrollRepo, $empRepo, $journalService, $this->pdo);
        $leaveService = new LeaveService($leaveRepo, $empRepo);

        $action = new HrAction($employeeService, $payrollService, $leaveService);

        $uuid = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}';
        $app->group('', function ($g) use ($action, $uuid): void {
            HrRoutes::register($g, $action, $uuid);
        });

        $app->addRoutingMiddleware();
        $app->add($companyMiddleware);
        $errorMiddleware = $app->addErrorMiddleware(false, true, true);
        $errorMiddleware->setDefaultErrorHandler(ApiErrorHandler::create($app->getResponseFactory()));

        return $app;
    }

    private function request(string $method, string $path, array $headers = []): ResponseInterface
    {
        $requestFactory = new ServerRequestFactory();
        $request = $requestFactory->createServerRequest($method, $path);
        foreach ($headers as $name => $value) {
            $request = $request->withHeader($name, $value);
        }

        return $this->app->handle($request);
    }

    private function jsonRequest(string $method, string $path, array $payload, array $headers = []): ResponseInterface
    {
        $streamFactory = new StreamFactory();
        $requestFactory = new ServerRequestFactory();
        $body = $streamFactory->createStream((string) json_encode($payload, JSON_THROW_ON_ERROR));

        $request = $requestFactory
            ->createServerRequest($method, $path)
            ->withHeader('Content-Type', 'application/json')
            ->withBody($body);

        foreach ($headers as $name => $value) {
            $request = $request->withHeader($name, $value);
        }

        return $this->app->handle($request);
    }

    private function decodeBody(ResponseInterface $response): array
    {
        $raw = (string) $response->getBody();
        $data = json_decode($raw, true);

        return is_array($data) ? $data : [];
    }

    private function issueToken(string $userId, string $role): string
    {
        return JWT::encode([
            'sub' => $userId,
            'role' => $role,
            'lang' => 'es',
            'iat' => time(),
            'exp' => time() + 3600,
        ], (string) $_ENV['JWT_SECRET'], 'HS256');
    }

    private function createSchema(): void
    {
        $this->pdo->exec("ATTACH DATABASE ':memory:' AS auth");
        $this->pdo->exec("ATTACH DATABASE ':memory:' AS hr");

        $this->pdo->exec(
            'CREATE TABLE auth.roles (
                id TEXT PRIMARY KEY,
                name_es TEXT NOT NULL UNIQUE,
                name_en TEXT NOT NULL UNIQUE,
                description_es TEXT,
                description_en TEXT,
                is_active INTEGER NOT NULL DEFAULT 1
            )',
        );

        $this->pdo->exec(
            'CREATE TABLE auth.users (
                id TEXT PRIMARY KEY,
                name TEXT NOT NULL,
                email TEXT NOT NULL UNIQUE,
                password_hash TEXT NULL,
                language TEXT NOT NULL DEFAULT "es",
                is_active INTEGER NOT NULL DEFAULT 1
            )',
        );

        $this->pdo->exec(
            'CREATE TABLE auth.role_user (
                role_id TEXT NOT NULL,
                user_id TEXT NOT NULL,
                PRIMARY KEY (role_id, user_id)
            )',
        );

        $this->pdo->exec(
            'CREATE TABLE companies (
                id TEXT PRIMARY KEY,
                legal_name TEXT NOT NULL,
                trade_name TEXT,
                tax_id TEXT NOT NULL UNIQUE,
                base_currency TEXT NOT NULL DEFAULT "USD",
                email TEXT,
                phone TEXT,
                address TEXT,
                is_active INTEGER NOT NULL DEFAULT 1,
                created_at TEXT DEFAULT CURRENT_TIMESTAMP,
                updated_at TEXT DEFAULT CURRENT_TIMESTAMP
            )',
        );

        $this->pdo->exec(
            'CREATE TABLE branches (
                id TEXT PRIMARY KEY,
                company_id TEXT NOT NULL,
                name TEXT NOT NULL,
                code TEXT,
                address TEXT,
                phone TEXT,
                is_main INTEGER NOT NULL DEFAULT 0,
                operating_currency TEXT NOT NULL DEFAULT "USD",
                is_active INTEGER NOT NULL DEFAULT 1,
                created_at TEXT DEFAULT CURRENT_TIMESTAMP,
                updated_at TEXT DEFAULT CURRENT_TIMESTAMP,
                UNIQUE (company_id, code)
            )',
        );

        $this->pdo->exec(
            'CREATE TABLE user_access (
                id TEXT PRIMARY KEY,
                user_id TEXT NOT NULL,
                company_id TEXT NOT NULL,
                branch_id TEXT,
                can_manage INTEGER NOT NULL DEFAULT 0,
                is_default INTEGER NOT NULL DEFAULT 0,
                created_at TEXT DEFAULT CURRENT_TIMESTAMP,
                UNIQUE (user_id, company_id)
            )',
        );

        $this->pdo->exec(
            'CREATE TABLE chart_accounts (
                id TEXT PRIMARY KEY,
                parent_id TEXT NULL,
                company_id TEXT NOT NULL,
                code TEXT NOT NULL,
                name TEXT NOT NULL,
                account_type TEXT NOT NULL,
                is_header INTEGER NOT NULL DEFAULT 0,
                is_active INTEGER NOT NULL DEFAULT 1,
                created_at TEXT DEFAULT CURRENT_TIMESTAMP,
                updated_at TEXT DEFAULT CURRENT_TIMESTAMP,
                UNIQUE (company_id, code)
            )'
        );

        $this->pdo->exec(
            'CREATE TABLE journal_entries (
                id TEXT PRIMARY KEY,
                company_id TEXT NOT NULL,
                branch_id TEXT,
                entry_number TEXT NOT NULL,
                entry_date TEXT NOT NULL,
                description TEXT,
                status TEXT NOT NULL DEFAULT "draft",
                operating_currency TEXT NOT NULL,
                functional_currency TEXT NOT NULL,
                exchange_rate REAL NOT NULL,
                created_by TEXT,
                created_at TEXT DEFAULT CURRENT_TIMESTAMP,
                updated_at TEXT DEFAULT CURRENT_TIMESTAMP,
                UNIQUE (company_id, entry_number)
            )'
        );

        $this->pdo->exec(
            'CREATE TABLE journal_lines (
                id TEXT PRIMARY KEY,
                journal_entry_id TEXT NOT NULL REFERENCES journal_entries(id) ON DELETE CASCADE,
                chart_account_id TEXT NOT NULL REFERENCES chart_accounts(id),
                description TEXT,
                debit REAL NOT NULL DEFAULT 0,
                credit REAL NOT NULL DEFAULT 0,
                debit_functional REAL NOT NULL DEFAULT 0,
                credit_functional REAL NOT NULL DEFAULT 0,
                line_order INTEGER NOT NULL DEFAULT 0
            )'
        );

        // HR tables
        $this->pdo->exec(
            'CREATE TABLE hr.departments (
                id TEXT PRIMARY KEY,
                company_id TEXT NOT NULL,
                name TEXT NOT NULL,
                is_active INTEGER NOT NULL DEFAULT 1,
                created_at TEXT DEFAULT CURRENT_TIMESTAMP,
                updated_at TEXT DEFAULT CURRENT_TIMESTAMP
            )'
        );

        $this->pdo->exec(
            'CREATE TABLE hr.employees (
                id TEXT PRIMARY KEY,
                company_id TEXT NOT NULL,
                first_name TEXT NOT NULL,
                last_name TEXT NOT NULL,
                email TEXT NOT NULL,
                phone TEXT,
                identification_number TEXT NOT NULL,
                hiring_date TEXT NOT NULL,
                department_id TEXT,
                is_active INTEGER NOT NULL DEFAULT 1,
                created_at TEXT DEFAULT CURRENT_TIMESTAMP,
                updated_at TEXT DEFAULT CURRENT_TIMESTAMP,
                UNIQUE (company_id, identification_number)
            )'
        );

        $this->pdo->exec(
            'CREATE TABLE hr.contracts (
                id TEXT PRIMARY KEY,
                employee_id TEXT NOT NULL,
                contract_type TEXT NOT NULL,
                start_date TEXT NOT NULL,
                end_date TEXT,
                base_salary REAL NOT NULL DEFAULT 0,
                status TEXT NOT NULL DEFAULT "active",
                created_at TEXT DEFAULT CURRENT_TIMESTAMP,
                updated_at TEXT DEFAULT CURRENT_TIMESTAMP
            )'
        );

        $this->pdo->exec(
            'CREATE TABLE hr.payrolls (
                id TEXT PRIMARY KEY,
                company_id TEXT NOT NULL,
                name TEXT NOT NULL,
                start_date TEXT NOT NULL,
                end_date TEXT NOT NULL,
                total_earnings REAL NOT NULL DEFAULT 0,
                total_deductions REAL NOT NULL DEFAULT 0,
                total_net REAL NOT NULL DEFAULT 0,
                status TEXT NOT NULL DEFAULT "draft",
                journal_entry_id TEXT,
                created_at TEXT DEFAULT CURRENT_TIMESTAMP,
                updated_at TEXT DEFAULT CURRENT_TIMESTAMP
            )'
        );

        $this->pdo->exec(
            'CREATE TABLE hr.payroll_lines (
                id TEXT PRIMARY KEY,
                payroll_id TEXT NOT NULL,
                employee_id TEXT NOT NULL,
                base_salary REAL NOT NULL DEFAULT 0,
                bonuses REAL NOT NULL DEFAULT 0,
                deductions REAL NOT NULL DEFAULT 0,
                net_pay REAL NOT NULL DEFAULT 0,
                created_at TEXT DEFAULT CURRENT_TIMESTAMP
            )'
        );

        $this->pdo->exec(
            'CREATE TABLE hr.leaves (
                id TEXT PRIMARY KEY,
                employee_id TEXT NOT NULL,
                leave_type TEXT NOT NULL,
                start_date TEXT NOT NULL,
                end_date TEXT NOT NULL,
                status TEXT NOT NULL DEFAULT "pending",
                notes TEXT,
                created_at TEXT DEFAULT CURRENT_TIMESTAMP,
                updated_at TEXT DEFAULT CURRENT_TIMESTAMP
            )'
        );
    }

    private function seedData(): void
    {
        $this->pdo->prepare(
            'INSERT INTO auth.users (id, name, email, password_hash, is_active) VALUES (?,?,?, "hash", 1)'
        )->execute([self::ADMIN_USER_ID, 'Admin User', 'admin@example.com']);

        $this->pdo->prepare(
            'INSERT INTO auth.roles (id, name_es, name_en) VALUES (?,?,?)'
        )->execute([self::ADMIN_ROLE_ID, 'ADMINISTRADOR', 'ADMINISTRATOR']);

        $this->pdo->prepare('INSERT INTO auth.role_user (role_id, user_id) VALUES (?,?)')
            ->execute([self::ADMIN_ROLE_ID, self::ADMIN_USER_ID]);

        $this->pdo->prepare(
            'INSERT INTO companies (id, legal_name, trade_name, tax_id, base_currency, is_active)
             VALUES (?,?,?,?,?,1)'
        )->execute([self::COMPANY_ID, 'Empresa Demo', 'Demo', '900111222-3', 'USD']);

        $this->pdo->prepare(
            'INSERT INTO branches (id, company_id, name, code, is_main, operating_currency, is_active)
             VALUES (?,?,?,?,1,?,1)'
        )->execute([self::BRANCH_ID, self::COMPANY_ID, 'Principal', 'MAIN', 'USD']);

        $this->pdo->prepare(
            'INSERT INTO user_access (id, user_id, company_id, branch_id, can_manage, is_default)
             VALUES (?,?,?,?,1,1)'
        )->execute(['cccccccc-cccc-cccc-cccc-cccccccccccc', self::ADMIN_USER_ID, self::COMPANY_ID, self::BRANCH_ID]);

        // Seed accounts
        $this->pdo->prepare('INSERT INTO chart_accounts (id, company_id, code, name, account_type, is_header) VALUES (?,?,?,?,?,0)')
            ->execute([self::EXPENSE_ACCOUNT_ID, self::COMPANY_ID, '5105', 'Gastos de Personal', 'expense']);

        $this->pdo->prepare('INSERT INTO chart_accounts (id, company_id, code, name, account_type, is_header) VALUES (?,?,?,?,?,0)')
            ->execute([self::BANK_ACCOUNT_ID, self::COMPANY_ID, '1110', 'Bancos', 'asset']);

        $this->pdo->prepare('INSERT INTO chart_accounts (id, company_id, code, name, account_type, is_header) VALUES (?,?,?,?,?,0)')
            ->execute([self::DEDUCTIONS_ACCOUNT_ID, self::COMPANY_ID, '2105', 'Deducciones', 'liability']);
    }

    private function configureEnv(): void
    {
        $_ENV['JWT_SECRET'] = 'test-jwt-secret';
        $_ENV['JWT_EXPIRES_IN'] = '15m';
        $_ENV['JWT_REFRESH_EXPIRES_DAYS'] = '7';
        $_ENV['JWT_KID'] = '';
        $_ENV['JWT_SECRET_PREVIOUS'] = '';
    }
}
