using MediatR;
using Microsoft.AspNetCore.Identity;
using TakeoutSaaS.Application.App.Tenants.Commands;
using TakeoutSaaS.Application.App.Tenants.Dto;
using TakeoutSaaS.Application.Identity.Commands;
using TakeoutSaaS.Domain.Identity.Entities;
using TakeoutSaaS.Domain.Identity.Repositories;
using TakeoutSaaS.Domain.Tenants.Entities;
using TakeoutSaaS.Domain.Tenants.Enums;
using TakeoutSaaS.Domain.Tenants.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;
using TakeoutSaaS.Shared.Abstractions.Ids;
using TakeoutSaaS.Shared.Abstractions.Tenancy;

namespace TakeoutSaaS.Application.App.Tenants.Handlers;

/// <summary>
/// 自助注册租户处理器。
/// </summary>
public sealed class SelfRegisterTenantCommandHandler(
    ITenantRepository tenantRepository,
    IIdentityUserRepository identityUserRepository,
    IRoleRepository roleRepository,
    IPasswordHasher<IdentityUser> passwordHasher,
    IIdGenerator idGenerator,
    IMediator mediator,
    ITenantContextAccessor tenantContextAccessor)
    : IRequestHandler<SelfRegisterTenantCommand, SelfRegisterResultDto>
{
    /// <inheritdoc />
    public async Task<SelfRegisterResultDto> Handle(SelfRegisterTenantCommand request, CancellationToken cancellationToken)
    {
        // 1. 唯一性校验
        var normalizedAccount = request.AdminAccount.Trim();
        if (await identityUserRepository.ExistsByAccountAsync(normalizedAccount, cancellationToken))
        {
            throw new BusinessException(ErrorCodes.Conflict, $"账号 {normalizedAccount} 已存在");
        }

        // 1.2 校验手机号唯一性
        var normalizedPhone = request.AdminPhone.Trim();
        if (await tenantRepository.ExistsByContactPhoneAsync(normalizedPhone, cancellationToken))
        {
            throw new BusinessException(ErrorCodes.Conflict, $"手机号 {normalizedPhone} 已注册");
        }

        // 2. 生成租户标识与编码
        var tenantId = idGenerator.NextId();
        var tenantCode = $"t{tenantId}";

        // 3. 构建租户（无订阅，待审核）
        var tenant = new Tenant
        {
            Id = tenantId,
            Code = tenantCode,
            Name = normalizedAccount,
            ShortName = string.IsNullOrWhiteSpace(request.AdminDisplayName) ? normalizedAccount : request.AdminDisplayName!.Trim(),
            ContactName = string.IsNullOrWhiteSpace(request.AdminDisplayName) ? normalizedAccount : request.AdminDisplayName!.Trim(),
            ContactPhone = normalizedPhone,
            ContactEmail = request.AdminEmail,
            Status = TenantStatus.PendingReview,
            EffectiveFrom = null,
            EffectiveTo = null
        };

        // 4. 写入审计日志
        var auditLog = new TenantAuditLog
        {
            TenantId = tenant.Id,
            Action = TenantAuditAction.RegistrationSubmitted,
            Title = "自助注册",
            Description = "自助注册提交，等待补充资料与审核"
        };

        // 5. 持久化租户与审计
        await tenantRepository.AddTenantAsync(tenant, cancellationToken);
        await tenantRepository.AddAuditLogAsync(auditLog, cancellationToken);
        await tenantRepository.SaveChangesAsync(cancellationToken);

        // 6. 临时切换租户上下文，保证身份与权限写入正确
        var previousContext = tenantContextAccessor.Current;
        tenantContextAccessor.Current = new TenantContext(tenant.Id, tenant.Code, "self-register");
        try
        {
            // 7. 使用用户自设密码创建管理员
            var adminUser = new IdentityUser
            {
                TenantId = tenant.Id,
                Account = normalizedAccount,
                DisplayName = string.IsNullOrWhiteSpace(request.AdminDisplayName) ? normalizedAccount : request.AdminDisplayName!.Trim(),
                PasswordHash = string.Empty
            };
            adminUser.PasswordHash = passwordHasher.HashPassword(adminUser, request.AdminPassword);
            await identityUserRepository.AddAsync(adminUser, cancellationToken);
            await identityUserRepository.SaveChangesAsync(cancellationToken);

            // 8. 初始化租户管理员角色模板
            await mediator.Send(new InitializeRoleTemplatesCommand
            {
                TemplateCodes = new[] { "tenant-admin" }
            }, cancellationToken);

            // 9. 绑定租户管理员角色
            var tenantAdminRole = await roleRepository.FindByCodeAsync("tenant-admin", tenant.Id, cancellationToken);
            if (tenantAdminRole != null)
            {
                await mediator.Send(new AssignUserRolesCommand
                {
                    UserId = adminUser.Id,
                    RoleIds = new[] { tenantAdminRole.Id }
                }, cancellationToken);
            }

            // 10. 返回注册结果
            return new SelfRegisterResultDto
            {
                TenantId = tenant.Id,
                Code = tenant.Code,
                Status = tenant.Status,
                VerificationStatus = TenantVerificationStatus.Draft,
                EffectiveFrom = tenant.EffectiveFrom,
                EffectiveTo = tenant.EffectiveTo,
                AdminAccount = adminUser.Account
            };
        }
        finally
        {
            // 11. 恢复上下文
            tenantContextAccessor.Current = previousContext;
        }
    }
}
