using Health.Application.Admin;

namespace Health.Infrastructure.Admin;

public sealed class AdminService(AppDbContext db) : IAdminService
{
    private readonly AppDbContext _db = db;

    public async Task<AdminResult> ListDoctorsAsync(CancellationToken ct)
    {
        var doctors = await _db.Doctors.AsNoTracking().OrderBy(x => x.CreatedAt)
            .Select(x => new { x.Id, x.Name, x.Title, x.Department, x.Phone, x.ProfessionalDirection, x.IsActive, x.AvatarUrl, x.Introduction, x.CreatedAt })
            .ToListAsync(ct);
        return Ok(doctors);
    }

    public async Task<AdminResult> AddDoctorAsync(AddDoctorCommand command, CancellationToken ct)
    {
        if (string.IsNullOrWhiteSpace(command.Phone)) return Error(40001, "手机号不能为空");
        if (string.IsNullOrWhiteSpace(command.Name)) return Error(40002, "姓名不能为空");
        var doctor = new Doctor
        {
            Id = Guid.NewGuid(), Name = command.Name, Title = command.Title, Department = command.Department,
            Phone = command.Phone, ProfessionalDirection = command.ProfessionalDirection, IsActive = true, CreatedAt = DateTime.UtcNow,
        };
        _db.Doctors.Add(doctor);
        if (!await _db.Users.AnyAsync(x => x.Phone == command.Phone, ct))
        {
            var user = new User { Id = Guid.NewGuid(), Phone = command.Phone, Role = "Doctor", Name = command.Name, CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow };
            _db.Users.Add(user);
            _db.DoctorProfiles.Add(new DoctorProfile
            {
                Id = Guid.NewGuid(), UserId = user.Id, DoctorId = doctor.Id, Name = command.Name,
                Title = command.Title, Department = command.Department, IsActive = true,
                CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow,
            });
        }
        await _db.SaveChangesAsync(ct);
        return Ok(new { doctor.Id, doctor.Name });
    }

    public async Task<AdminResult> UpdateDoctorAsync(Guid id, UpdateDoctorCommand command, CancellationToken ct)
    {
        var doctor = await _db.Doctors.FindAsync([id], ct);
        if (doctor == null) return Error(404, "医生不存在");
        if (command.Name != null) doctor.Name = command.Name;
        if (command.Title != null) doctor.Title = command.Title;
        if (command.Department != null) doctor.Department = command.Department;
        if (command.Phone != null) doctor.Phone = command.Phone;
        if (command.ProfessionalDirection != null) doctor.ProfessionalDirection = command.ProfessionalDirection;
        await _db.SaveChangesAsync(ct);
        return Ok(new { doctor.Id });
    }

    public async Task<AdminResult> ToggleDoctorAsync(Guid id, CancellationToken ct)
    {
        var doctor = await _db.Doctors.FindAsync([id], ct);
        if (doctor == null) return Error(404, "医生不存在");
        doctor.IsActive = !doctor.IsActive;
        await _db.SaveChangesAsync(ct);
        return Ok(new { doctor.Id, doctor.IsActive });
    }

    public async Task<AdminResult> DeleteDoctorAsync(Guid id, CancellationToken ct)
    {
        var doctor = await _db.Doctors.FindAsync([id], ct);
        if (doctor == null) return Error(404, "医生不存在");
        await _db.Users.Where(x => x.DoctorId == id).ExecuteUpdateAsync(s => s.SetProperty(x => x.DoctorId, (Guid?)null), ct);
        _db.Doctors.Remove(doctor);
        await _db.SaveChangesAsync(ct);
        return Ok(new { success = true });
    }

    public async Task<AdminResult> ListPatientsAsync(string? search, int page, int pageSize, CancellationToken ct)
    {
        page = Math.Max(page, 1);
        pageSize = Math.Clamp(pageSize, 1, 100);
        var query = _db.Users.AsNoTracking().Where(x => x.Role == "User");
        if (!string.IsNullOrWhiteSpace(search))
            query = query.Where(x => (x.Name != null && x.Name.Contains(search)) || x.Phone.Contains(search));
        var total = await query.CountAsync(ct);
        var patients = await query.OrderByDescending(x => x.CreatedAt).Skip((page - 1) * pageSize).Take(pageSize)
            .Select(x => new { x.Id, x.Name, x.Phone, x.Gender, x.BirthDate, x.CreatedAt, DoctorName = x.Doctor != null ? x.Doctor.Name : null, DoctorDepartment = x.Doctor != null ? x.Doctor.Department : null })
            .ToListAsync(ct);
        return Ok(new { patients, total, page, pageSize });
    }

    private static AdminResult Ok(object data) => new(0, data);
    private static AdminResult Error(int code, string message) => new(code, null, message);
}
