using System.Collections.Generic;
using System.Data;
using System.Threading;
using System.Threading.Tasks;
using Dapper;
using TaxBaik.Domain.Entities;
using TaxBaik.Domain.Interfaces;

namespace TaxBaik.Infrastructure.Repositories;

public class CommonCodeRepository(IDbConnectionFactory connectionFactory) : BaseRepository(connectionFactory), ICommonCodeRepository
{
    public async Task<IEnumerable<string>> GetAllGroupsAsync(CancellationToken ct = default)
    {
        using var conn = Conn();
        return await conn.QueryAsync<string>(
            "SELECT DISTINCT code_group FROM common_codes WHERE is_active = TRUE ORDER BY code_group");
    }

    public async Task<IEnumerable<CommonCode>> GetByGroupAsync(string codeGroup, CancellationToken ct = default)
    {
        using var conn = Conn();
        return await conn.QueryAsync<CommonCode>(
            @"SELECT code_group as CodeGroup, code_value as CodeValue, code_name as CodeName, sort_order as SortOrder, is_active as IsActive
              FROM common_codes 
              WHERE code_group = @CodeGroup AND is_active = TRUE 
              ORDER BY sort_order",
            new { CodeGroup = codeGroup });
    }

    public async Task<IEnumerable<CommonCode>> GetAllActiveAsync(CancellationToken ct = default)
    {
        using var conn = Conn();
        return await conn.QueryAsync<CommonCode>(
            @"SELECT code_group as CodeGroup, code_value as CodeValue, code_name as CodeName, sort_order as SortOrder, is_active as IsActive
              FROM common_codes 
              WHERE is_active = TRUE 
              ORDER BY code_group, sort_order");
    }

    public async Task<CommonCode?> GetAsync(string codeGroup, string codeValue, CancellationToken ct = default)
    {
        using var conn = Conn();
        return await conn.QuerySingleOrDefaultAsync<CommonCode>(
            @"SELECT code_group as CodeGroup, code_value as CodeValue, code_name as CodeName, sort_order as SortOrder, is_active as IsActive
              FROM common_codes
              WHERE code_group = @CodeGroup AND code_value = @CodeValue",
            new { CodeGroup = codeGroup, CodeValue = codeValue });
    }

    public async Task UpsertAsync(CommonCode code, CancellationToken ct = default)
    {
        using var conn = Conn();
        await conn.ExecuteAsync(
            @"INSERT INTO common_codes (code_group, code_value, code_name, sort_order, is_active)
              VALUES (@CodeGroup, @CodeValue, @CodeName, @SortOrder, @IsActive)
              ON CONFLICT (code_group, code_value) DO UPDATE
              SET code_name = EXCLUDED.code_name,
                  sort_order = EXCLUDED.sort_order,
                  is_active = EXCLUDED.is_active",
            code);
    }

    public async Task DeleteAsync(string codeGroup, string codeValue, CancellationToken ct = default)
    {
        using var conn = Conn();
        await conn.ExecuteAsync(
            @"DELETE FROM common_codes
              WHERE code_group = @CodeGroup AND code_value = @CodeValue",
            new { CodeGroup = codeGroup, CodeValue = codeValue });
    }
}
