<?php

namespace Modules\LotesSeries\Services;

use PDO;
use Exception;

/**
 * Serviço para gestão de números de série
 */
class SerieService {
    private PDO $pdo;
    private string $tenantId;

    public function __construct(string $tenantId) {
        $this->tenantId = $tenantId;
        $this->pdo = \Gestoreasy\Core\Tenant\ConnectionManager::forTenant($tenantId);
    }

    /**
     * Cria um novo número de série
     */
    public function criarSerie(array $dados): int {
        $this->pdo->beginTransaction();
        try {
            // Validar se produto existe
            $stmt = $this->pdo->prepare('SELECT id FROM products WHERE id = ?');
            $stmt->execute([$dados['product_id']]);
            if (!$stmt->fetch()) {
                throw new Exception('Produto não encontrado');
            }

            // Validar duplicata se configurado
            $config = $this->getConfig();
            if ($config['validar_serie_duplicada']) {
                $stmt = $this->pdo->prepare('
                    SELECT id FROM product_serial_numbers 
                    WHERE tenant_id = ? AND product_id = ? AND numero_serie = ?
                ');
                $stmt->execute([$this->tenantId, $dados['product_id'], $dados['numero_serie']]);
                if ($stmt->fetch()) {
                    throw new Exception('Número de série já existe para este produto');
                }
            }

            // Criar série
            $stmt = $this->pdo->prepare('
                INSERT INTO product_serial_numbers (
                    tenant_id, product_id, numero_serie,
                    warehouse_id, bin_id, fornecedor_id,
                    nota_fiscal_id, numero_nota_fiscal, lote_id,
                    data_compra, data_inicio_garantia, data_fim_garantia,
                    dias_garantia, observacoes
                ) VALUES (
                    ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
                )
            ');
            $stmt->execute([
                $this->tenantId,
                $dados['product_id'],
                $dados['numero_serie'],
                $dados['warehouse_id'] ?? null,
                $dados['bin_id'] ?? null,
                $dados['fornecedor_id'] ?? null,
                $dados['nota_fiscal_id'] ?? null,
                $dados['numero_nota_fiscal'] ?? null,
                $dados['lote_id'] ?? null,
                $dados['data_compra'] ?? null,
                $dados['data_inicio_garantia'] ?? null,
                $dados['data_fim_garantia'] ?? null,
                $dados['dias_garantia'] ?? null,
                $dados['observacoes'] ?? null,
            ]);

            $serieId = (int)$this->pdo->lastInsertId();

            // Registrar movimentação inicial
            $this->registrarMovimentacao($serieId, 'entrada', 'disponivel', 'disponivel', [
                'origem_tipo' => $dados['origem_tipo'] ?? 'compra',
                'origem_id' => $dados['origem_id'] ?? null,
                'origem_numero' => $dados['origem_numero'] ?? null,
                'motivo' => 'Criação da série'
            ]);

            $this->pdo->commit();
            return $serieId;
        } catch (Exception $e) {
            $this->pdo->rollBack();
            throw $e;
        }
    }

    /**
     * Valida se número de série já existe
     */
    public function validarSerie(int $productId, string $numeroSerie): array {
        $stmt = $this->pdo->prepare('
            SELECT id, status, cliente_id, venda_id
            FROM product_serial_numbers
            WHERE tenant_id = ? AND product_id = ? AND numero_serie = ?
        ');
        $stmt->execute([$this->tenantId, $productId, $numeroSerie]);
        $serie = $stmt->fetch(PDO::FETCH_ASSOC);

        return [
            'existe' => $serie !== false,
            'valido' => $serie === false || $serie['status'] === 'disponivel',
            'dados' => $serie ?: null
        ];
    }

    /**
     * Vincula série a uma venda
     */
    public function vincularVenda(int $serieId, int $vendaId, int $clienteId): void {
        $this->pdo->beginTransaction();
        try {
            // Buscar série
            $stmt = $this->pdo->prepare('SELECT * FROM product_serial_numbers WHERE id = ? AND tenant_id = ?');
            $stmt->execute([$serieId, $this->tenantId]);
            $serie = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$serie) {
                throw new Exception('Série não encontrada');
            }

            if ($serie['status'] !== 'disponivel' && $serie['status'] !== 'reservado') {
                throw new Exception('Série não está disponível para venda');
            }

            $statusAnterior = $serie['status'];

            // Atualizar série
            $stmt = $this->pdo->prepare('
                UPDATE product_serial_numbers
                SET status = "vendido",
                    venda_id = ?,
                    cliente_id = ?,
                    data_venda = CURDATE()
                WHERE id = ?
            ');
            $stmt->execute([$vendaId, $clienteId, $serieId]);

            // Registrar movimentação
            $this->registrarMovimentacao($serieId, 'saida', $statusAnterior, 'vendido', [
                'destino_tipo' => 'venda',
                'destino_id' => $vendaId,
                'destino_numero' => (string)$vendaId,
                'motivo' => 'Venda do produto'
            ]);

            $this->pdo->commit();
        } catch (Exception $e) {
            $this->pdo->rollBack();
            throw $e;
        }
    }

    /**
     * Registra movimentação de série
     */
    private function registrarMovimentacao(int $serieId, string $tipo, string $statusAnterior, string $statusNovo, array $dados = []): void {
        $userContext = \Gestoreasy\Core\Auth\UserContext::getCurrent();
        
        $stmt = $this->pdo->prepare('
            INSERT INTO serial_movements (
                tenant_id, serial_id, tipo, status_anterior, status_novo,
                origem_tipo, origem_id, origem_numero,
                destino_tipo, destino_id, destino_numero,
                warehouse_id_origem, warehouse_id_destino,
                motivo, observacoes, user_id
            ) VALUES (
                ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
            )
        ');
        $stmt->execute([
            $this->tenantId,
            $serieId,
            $tipo,
            $statusAnterior,
            $statusNovo,
            $dados['origem_tipo'] ?? null,
            $dados['origem_id'] ?? null,
            $dados['origem_numero'] ?? null,
            $dados['destino_tipo'] ?? null,
            $dados['destino_id'] ?? null,
            $dados['destino_numero'] ?? null,
            $dados['warehouse_id_origem'] ?? null,
            $dados['warehouse_id_destino'] ?? null,
            $dados['motivo'] ?? null,
            $dados['observacoes'] ?? null,
            $userContext?->userId,
        ]);
    }

    /**
     * Obtém configuração
     */
    private function getConfig(): array {
        $stmt = $this->pdo->prepare('SELECT * FROM lotes_series_config WHERE tenant_id = ?');
        $stmt->execute([$this->tenantId]);
        $config = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$config) {
            return [
                'validar_serie_duplicada' => true,
            ];
        }

        return $config;
    }
}

