<?php

declare(strict_types=1);

namespace ApiModel\Infrastructure\Persistence\Repositories;

use ApiModel\Domain\Repository\InventoryAdjustmentRepositoryInterface;
use ApiModel\Infrastructure\Persistence\Database;
use PDO;

final class PdoInventoryAdjustmentRepository implements InventoryAdjustmentRepositoryInterface
{
    public function __construct(private readonly PDO $pdo) {}

    public function findById(string $id): ?array
    {
        $st = $this->pdo->prepare('SELECT * FROM inventory_adjustments WHERE id = ? LIMIT 1');
        $st->execute([$id]);
        $row = $st->fetch(PDO::FETCH_ASSOC);
        return $row !== false ? $row : null;
    }

    public function listByCompany(string $companyId): array
    {
        $st = $this->pdo->prepare(
            'SELECT * FROM inventory_adjustments 
             WHERE company_id = ? 
             ORDER BY adjustment_date DESC, created_at DESC'
        );
        $st->execute([$companyId]);
        return $st->fetchAll(PDO::FETCH_ASSOC);
    }

    public function nextAdjustmentNumber(string $companyId): string
    {
        $st = $this->pdo->prepare('SELECT COUNT(*) FROM inventory_adjustments WHERE company_id = ?');
        $st->execute([$companyId]);
        $count = (int) $st->fetchColumn();
        return 'AJ-' . str_pad((string) ($count + 1), 6, '0', STR_PAD_LEFT);
    }

    public function insert(array $data): void
    {
        $st = $this->pdo->prepare(
            'INSERT INTO inventory_adjustments (
                id, company_id, branch_id, adjustment_number, adjustment_date, notes, created_by, created_at, updated_at
             ) VALUES (
                :id, :company_id, :branch_id, :adjustment_number, :adjustment_date, :notes, :created_by, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP
             )'
        );
        $st->execute([
            'id' => $data['id'],
            'company_id' => $data['company_id'],
            'branch_id' => $data['branch_id'] ?: null,
            'adjustment_number' => $data['adjustment_number'],
            'adjustment_date' => $data['adjustment_date'],
            'notes' => $data['notes'] ?: null,
            'created_by' => $data['created_by'] ?: null,
        ]);
    }

    public function delete(string $id): void
    {
        $st = $this->pdo->prepare('DELETE FROM inventory_adjustments WHERE id = ?');
        $st->execute([$id]);
    }

    public function findLinesByAdjustmentId(string $adjustmentId): array
    {
        $st = $this->pdo->prepare(
            'SELECT l.*, i.sku as item_sku, i.name as item_name, w.name as warehouse_name, a.code as account_code, a.name as account_name
             FROM inventory_adjustment_lines l
             JOIN inventory_items i ON l.item_id = i.id
             JOIN warehouses w ON l.warehouse_id = w.id
             JOIN chart_accounts a ON l.chart_account_id = a.id
             WHERE l.adjustment_id = ?'
        );
        $st->execute([$adjustmentId]);
        return $st->fetchAll(PDO::FETCH_ASSOC);
    }

    public function insertLines(string $adjustmentId, array $lines): void
    {
        $st = $this->pdo->prepare(
            'INSERT INTO inventory_adjustment_lines (
                id, adjustment_id, item_id, warehouse_id, quantity, unit_cost, chart_account_id
             ) VALUES (?, ?, ?, ?, ?, ?, ?)'
        );

        foreach ($lines as $line) {
            $id = $line['id'] ?? Database::uuid();
            $st->execute([
                $id,
                $adjustmentId,
                $line['item_id'],
                $line['warehouse_id'],
                $line['quantity'],
                $line['unit_cost'],
                $line['chart_account_id'],
            ]);
        }
    }

    public function deleteLines(string $adjustmentId): void
    {
        $st = $this->pdo->prepare('DELETE FROM inventory_adjustment_lines WHERE adjustment_id = ?');
        $st->execute([$adjustmentId]);
    }
}
