namespace TaxBaik.Application.Services;

using FluentValidation;
using TaxBaik.Application.DTOs;
using TaxBaik.Domain.Entities;
using TaxBaik.Domain.Interfaces;

public class ClientService(IClientRepository repository, IValidator<CreateClientDto> validator)
{
    public async Task<(IEnumerable<Client> Items, int Total)> GetPagedAsync(
        int page, int pageSize, string? status = null, string? search = null, CancellationToken ct = default) =>
        await repository.GetPagedAsync(Math.Max(1, page), Math.Clamp(pageSize, 1, 100), status, search, ct);

    public async Task<Client?> GetByIdAsync(int id, CancellationToken ct = default) =>
        await repository.GetByIdAsync(id, ct);

    public async Task<Client?> GetByEmailAsync(string email, CancellationToken ct = default) =>
        await repository.GetByEmailAsync(email, ct);

    public async Task<Client?> GetByPhoneAsync(string phone, CancellationToken ct = default) =>
        await repository.GetByPhoneAsync(phone, ct);

    public async Task<int> CountCreatedAtRangeAsync(DateTime startDateUtc, DateTime endDateUtc, CancellationToken ct = default) =>
        await repository.CountByCreatedAtRangeAsync(startDateUtc, endDateUtc, ct);

    public async Task<int> CreateAsync(CreateClientDto dto, CancellationToken ct = default)
    {
        validator.ValidateAndThrow(dto);

        var client = new Client
        {
            Name = dto.Name.Trim(),
            CompanyName = dto.CompanyName?.Trim(),
            Phone = dto.Phone?.Trim(),
            Email = dto.Email?.Trim(),
            ServiceType = dto.ServiceType,
            TaxType = dto.TaxType,
            Status = dto.Status,
            Source = dto.Source,
            Memo = dto.Memo?.Trim()
        };

        return await repository.CreateAsync(client, ct);
    }

    public async Task UpdateAsync(int id, CreateClientDto dto, CancellationToken ct = default)
    {
        validator.ValidateAndThrow(dto);

        var client = await repository.GetByIdAsync(id, ct)
            ?? throw new KeyNotFoundException($"고객 ID {id}를 찾을 수 없습니다.");

        client.Name = dto.Name.Trim();
        client.CompanyName = dto.CompanyName?.Trim();
        client.Phone = dto.Phone?.Trim();
        client.Email = dto.Email?.Trim();
        client.ServiceType = dto.ServiceType;
        client.TaxType = dto.TaxType;
        client.Status = dto.Status;
        client.Source = dto.Source;
        client.Memo = dto.Memo?.Trim();

        await repository.UpdateAsync(client, ct);
    }

    public async Task<int> CreateFromInquiryAsync(string name, string? phone, string? serviceType, CancellationToken ct = default)
    {
        var client = new Client
        {
            Name = name.Trim(),
            Phone = phone?.Trim(),
            ServiceType = serviceType,
            Status = "active",
            Source = "홈페이지문의"
        };
        return await repository.CreateAsync(client, ct);
    }

    public async Task DeleteAsync(int id, CancellationToken ct = default) =>
        await repository.DeleteAsync(id, ct);
}
