using Dapper;
// Asegúrate de que BCrypt.Net esté instalado en este proyecto o referenciado
// Si no te reconoce BCrypt, avísame, pero debería funcionar porque ya se usa en AuthService.

namespace SIGCM.Infrastructure.Data;

public class DbInitializer
{
    private readonly IDbConnectionFactory _connectionFactory;

    public DbInitializer(IDbConnectionFactory connectionFactory)
    {
        _connectionFactory = connectionFactory;
    }

    public async Task InitializeAsync()
    {
        using var connection = _connectionFactory.CreateConnection();

        var schemaSql = @"
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Users')
BEGIN
    CREATE TABLE Users (
        Id INT IDENTITY(1,1) PRIMARY KEY,
        Username NVARCHAR(50) NOT NULL UNIQUE,
        PasswordHash NVARCHAR(255) NOT NULL,
        Role NVARCHAR(20) NOT NULL,
        Email NVARCHAR(100) NULL,
        CreatedAt DATETIME DEFAULT GETUTCDATE()
    );
END

IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Categories')
BEGIN
    CREATE TABLE Categories (
        Id INT IDENTITY(1,1) PRIMARY KEY,
        ParentId INT NULL,
        Name NVARCHAR(100) NOT NULL,
        Slug NVARCHAR(100) NOT NULL,
        Active BIT DEFAULT 1,
        FOREIGN KEY (ParentId) REFERENCES Categories(Id)
    );
END

IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Operations')
BEGIN
    CREATE TABLE Operations (
        Id INT IDENTITY(1,1) PRIMARY KEY,
        Name NVARCHAR(50) NOT NULL UNIQUE
    );
END

IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'CategoryOperations')
BEGIN
    CREATE TABLE CategoryOperations (
        CategoryId INT NOT NULL,
        OperationId INT NOT NULL,
        PRIMARY KEY (CategoryId, OperationId),
        FOREIGN KEY (CategoryId) REFERENCES Categories(Id) ON DELETE CASCADE,
        FOREIGN KEY (OperationId) REFERENCES Operations(Id) ON DELETE CASCADE
    );
END

IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'AttributeDefinitions')
BEGIN
    CREATE TABLE AttributeDefinitions (
        Id INT IDENTITY(1,1) PRIMARY KEY,
        CategoryId INT NOT NULL,
        Name NVARCHAR(100) NOT NULL,
        DataType NVARCHAR(20) NOT NULL,
        Required BIT DEFAULT 0,
        FOREIGN KEY (CategoryId) REFERENCES Categories(Id) ON DELETE CASCADE
    );
END

IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Listings')
BEGIN
    CREATE TABLE Listings (
        Id INT IDENTITY(1,1) PRIMARY KEY,
        CategoryId INT NOT NULL,
        OperationId INT NOT NULL,
        Title NVARCHAR(200) NOT NULL,
        Description NVARCHAR(MAX) NULL,
        Price DECIMAL(18,2) NOT NULL DEFAULT 0,
        Currency NVARCHAR(3) DEFAULT 'ARS',
        CreatedAt DATETIME2 DEFAULT GETUTCDATE(),
        Status NVARCHAR(20) DEFAULT 'Draft',
        UserId INT NULL,
        FOREIGN KEY (CategoryId) REFERENCES Categories(Id),
        FOREIGN KEY (OperationId) REFERENCES Operations(Id),
        FOREIGN KEY (UserId) REFERENCES Users(Id)
    );
END

IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'ListingAttributeValues')
BEGIN
    CREATE TABLE ListingAttributeValues (
        Id INT IDENTITY(1,1) PRIMARY KEY,
        ListingId INT NOT NULL,
        AttributeDefinitionId INT NOT NULL,
        Value NVARCHAR(MAX) NOT NULL,
        FOREIGN KEY (ListingId) REFERENCES Listings(Id) ON DELETE CASCADE,
        FOREIGN KEY (AttributeDefinitionId) REFERENCES AttributeDefinitions(Id) ON DELETE NO ACTION
    );
END

IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'ListingImages')
BEGIN
    CREATE TABLE ListingImages (
        Id INT IDENTITY(1,1) PRIMARY KEY,
        ListingId INT NOT NULL,
        Url NVARCHAR(500) NOT NULL,
        IsMainInfo BIT DEFAULT 0,
        DisplayOrder INT DEFAULT 0,
        FOREIGN KEY (ListingId) REFERENCES Listings(Id) ON DELETE CASCADE
    );
END
";
        // Ejecutar creación de tablas
        await connection.ExecuteAsync(schemaSql);

        // --- SEED DE DATOS (Usuario Admin) ---
        var adminCount = await connection.ExecuteScalarAsync<int>("SELECT COUNT(1) FROM Users WHERE Username = 'admin'");

        if (adminCount == 0)
        {
            // Creamos el hash válido para la clave del usuario usando la librería del proyecto
            var passwordHash = BCrypt.Net.BCrypt.HashPassword("Diagonal423");

            var insertAdminSql = @"
                INSERT INTO Users (Username, PasswordHash, Role, Email)
                VALUES ('admin', @PasswordHash, 'Admin', 'admin@sigcm.com')";

            await connection.ExecuteAsync(insertAdminSql, new { PasswordHash = passwordHash });
        }
    }
}