using System.Text.Json;
using Microsoft.EntityFrameworkCore;
using MilitaryTrainingManagement.Data;
using MilitaryTrainingManagement.Models.Entities;
using MilitaryTrainingManagement.Models.Enums;
using MilitaryTrainingManagement.Services.Interfaces;

namespace MilitaryTrainingManagement.Services.Implementations;

/// <summary>
/// 审批工作流服务实现
/// </summary>
public class WorkflowService : IWorkflowService
{
    private readonly ApplicationDbContext _context;

    public WorkflowService(ApplicationDbContext context)
    {
        _context = context;
    }

    public async Task<ApprovalRequest?> GetByIdAsync(int id)
    {
        return await _context.ApprovalRequests
            .Include(r => r.RequestedByUser)
            .Include(r => r.RequestedByUnit)
            .Include(r => r.ReviewedByUser)
            .FirstOrDefaultAsync(r => r.Id == id);
    }

    public async Task<IEnumerable<ApprovalRequest>> GetPendingRequestsAsync()
    {
        return await _context.ApprovalRequests
            .Include(r => r.RequestedByUser)
            .Include(r => r.RequestedByUnit)
            .Where(r => r.Status == ApprovalStatus.Pending)
            .OrderByDescending(r => r.RequestedAt)
            .ToListAsync();
    }

    public async Task<IEnumerable<ApprovalRequest>> GetAllRequestsAsync(ApprovalStatus? status = null)
    {
        var query = _context.ApprovalRequests
            .Include(r => r.RequestedByUser)
            .Include(r => r.RequestedByUnit)
            .Include(r => r.ReviewedByUser)
            .AsQueryable();

        if (status.HasValue)
        {
            query = query.Where(r => r.Status == status.Value);
        }

        return await query.OrderByDescending(r => r.RequestedAt).ToListAsync();
    }

    public async Task<IEnumerable<ApprovalRequest>> GetRequestsByUnitAsync(int unitId, ApprovalStatus? status = null)
    {
        var query = _context.ApprovalRequests
            .Include(r => r.RequestedByUser)
            .Include(r => r.RequestedByUnit)
            .Include(r => r.ReviewedByUser)
            .Where(r => r.RequestedByUnitId == unitId);

        if (status.HasValue)
        {
            query = query.Where(r => r.Status == status.Value);
        }

        return await query.OrderByDescending(r => r.RequestedAt).ToListAsync();
    }


    public async Task<IEnumerable<ApprovalRequest>> GetRequestsByTypeAsync(ApprovalRequestType type, ApprovalStatus? status = null)
    {
        var query = _context.ApprovalRequests
            .Include(r => r.RequestedByUser)
            .Include(r => r.RequestedByUnit)
            .Include(r => r.ReviewedByUser)
            .Where(r => r.Type == type);

        if (status.HasValue)
        {
            query = query.Where(r => r.Status == status.Value);
        }

        return await query.OrderByDescending(r => r.RequestedAt).ToListAsync();
    }

    public async Task<ApprovalRequest> CreateModificationRequestAsync(
        ApprovalRequestType type,
        int targetEntityId,
        int requestedByUserId,
        int requestedByUnitId,
        string reason,
        string originalData,
        string requestedChanges)
    {
        // 验证目标实体是否存在
        var entityExists = await ValidateTargetEntityExistsAsync(type, targetEntityId);
        if (!entityExists)
        {
            throw new ArgumentException("目标实体不存在");
        }

        // 检查是否已有待处理的修改请求
        var hasPending = await HasPendingModificationRequestAsync(type, targetEntityId);
        if (hasPending)
        {
            throw new InvalidOperationException("该记录已有待处理的修改请求");
        }

        var request = new ApprovalRequest
        {
            Type = type,
            TargetEntityId = targetEntityId,
            RequestedByUserId = requestedByUserId,
            RequestedByUnitId = requestedByUnitId,
            Reason = reason,
            OriginalData = originalData,
            RequestedChanges = requestedChanges,
            Status = ApprovalStatus.Pending,
            RequestedAt = DateTime.UtcNow
        };

        _context.ApprovalRequests.Add(request);
        await _context.SaveChangesAsync();
        
        return request;
    }

    public async Task<ApprovalRequest> ApproveAsync(int requestId, int reviewedByUserId, string? comments)
    {
        var request = await _context.ApprovalRequests
            .Include(r => r.RequestedByUser)
            .FirstOrDefaultAsync(r => r.Id == requestId);
            
        if (request == null)
            throw new ArgumentException("审批请求不存在");

        if (request.Status != ApprovalStatus.Pending)
            throw new InvalidOperationException("只能审批待处理的请求");

        // 验证审批人权限（仅师团级别可审批）
        var canApprove = await CanUserApproveAsync(reviewedByUserId);
        if (!canApprove)
            throw new UnauthorizedAccessException("只有师团级别用户才能审批请求");

        request.Status = ApprovalStatus.Approved;
        request.ReviewedByUserId = reviewedByUserId;
        request.ReviewComments = comments;
        request.ReviewedAt = DateTime.UtcNow;

        // 应用修改到目标实体
        await ApplyApprovedChangesAsync(request);

        await _context.SaveChangesAsync();
        return request;
    }


    public async Task<ApprovalRequest> RejectAsync(int requestId, int reviewedByUserId, string? comments)
    {
        var request = await _context.ApprovalRequests.FindAsync(requestId);
        if (request == null)
            throw new ArgumentException("审批请求不存在");

        if (request.Status != ApprovalStatus.Pending)
            throw new InvalidOperationException("只能拒绝待处理的请求");

        // 验证审批人权限（仅师团级别可审批）
        var canApprove = await CanUserApproveAsync(reviewedByUserId);
        if (!canApprove)
            throw new UnauthorizedAccessException("只有师团级别用户才能拒绝请求");

        request.Status = ApprovalStatus.Rejected;
        request.ReviewedByUserId = reviewedByUserId;
        request.ReviewComments = comments;
        request.ReviewedAt = DateTime.UtcNow;

        await _context.SaveChangesAsync();
        return request;
    }

    public async Task<bool> IsRecordApprovedAsync(ApprovalRequestType type, int entityId)
    {
        switch (type)
        {
            case ApprovalRequestType.ReportModification:
                var distribution = await _context.AllocationDistributions
                    .FirstOrDefaultAsync(d => d.Id == entityId);
                return distribution?.IsApproved ?? false;

            case ApprovalRequestType.AllocationModification:
                // 配额修改：检查是否有已审批的分配记录
                var allocation = await _context.MaterialAllocations
                    .Include(a => a.Distributions)
                    .FirstOrDefaultAsync(a => a.Id == entityId);
                return allocation?.Distributions.Any(d => d.IsApproved) ?? false;

            case ApprovalRequestType.PersonnelModification:
                var personnel = await _context.Personnel
                    .FirstOrDefaultAsync(p => p.Id == entityId);
                return personnel?.Status == PersonnelStatus.Approved;

            default:
                return false;
        }
    }

    public async Task<bool> HasPendingModificationRequestAsync(ApprovalRequestType type, int entityId)
    {
        return await _context.ApprovalRequests
            .AnyAsync(r => r.Type == type 
                && r.TargetEntityId == entityId 
                && r.Status == ApprovalStatus.Pending);
    }

    public async Task<bool> CanUserApproveAsync(int userId)
    {
        var user = await _context.UserAccounts
            .Include(u => u.OrganizationalUnit)
            .FirstOrDefaultAsync(u => u.Id == userId);

        if (user == null)
            return false;

        // 只有师团级别用户可以审批
        return user.OrganizationalUnit.Level == OrganizationalLevel.Division;
    }


    /// <summary>
    /// 验证目标实体是否存在
    /// </summary>
    private async Task<bool> ValidateTargetEntityExistsAsync(ApprovalRequestType type, int entityId)
    {
        return type switch
        {
            ApprovalRequestType.AllocationModification => 
                await _context.MaterialAllocations.AnyAsync(a => a.Id == entityId),
            ApprovalRequestType.ReportModification => 
                await _context.AllocationDistributions.AnyAsync(d => d.Id == entityId),
            ApprovalRequestType.PersonnelModification => 
                await _context.Personnel.AnyAsync(p => p.Id == entityId),
            _ => false
        };
    }

    /// <summary>
    /// 应用已审批的修改到目标实体
    /// </summary>
    private async Task ApplyApprovedChangesAsync(ApprovalRequest request)
    {
        switch (request.Type)
        {
            case ApprovalRequestType.ReportModification:
                await ApplyReportModificationAsync(request);
                break;
            case ApprovalRequestType.AllocationModification:
                await ApplyAllocationModificationAsync(request);
                break;
            case ApprovalRequestType.PersonnelModification:
                await ApplyPersonnelModificationAsync(request);
                break;
        }
    }

    /// <summary>
    /// 应用上报修改
    /// </summary>
    private async Task ApplyReportModificationAsync(ApprovalRequest request)
    {
        var distribution = await _context.AllocationDistributions
            .FirstOrDefaultAsync(d => d.Id == request.TargetEntityId);

        if (distribution == null)
            throw new InvalidOperationException("目标上报记录不存在");

        try
        {
            var changes = JsonSerializer.Deserialize<ReportModificationChanges>(request.RequestedChanges);
            if (changes != null)
            {
                if (changes.ActualCompletion.HasValue)
                {
                    distribution.ActualCompletion = changes.ActualCompletion.Value;
                }
                distribution.ReportedAt = DateTime.UtcNow;
            }
        }
        catch (JsonException)
        {
            throw new InvalidOperationException("修改数据格式无效");
        }
    }

    /// <summary>
    /// 应用配额修改
    /// </summary>
    private async Task ApplyAllocationModificationAsync(ApprovalRequest request)
    {
        var allocation = await _context.MaterialAllocations
            .FirstOrDefaultAsync(a => a.Id == request.TargetEntityId);

        if (allocation == null)
            throw new InvalidOperationException("目标配额记录不存在");

        try
        {
            var changes = JsonSerializer.Deserialize<AllocationModificationChanges>(request.RequestedChanges);
            if (changes != null)
            {
                if (!string.IsNullOrEmpty(changes.Category))
                    allocation.Category = changes.Category;
                if (!string.IsNullOrEmpty(changes.MaterialName))
                    allocation.MaterialName = changes.MaterialName;
                if (!string.IsNullOrEmpty(changes.Unit))
                    allocation.Unit = changes.Unit;
                if (changes.TotalQuota.HasValue)
                    allocation.TotalQuota = changes.TotalQuota.Value;
            }
        }
        catch (JsonException)
        {
            throw new InvalidOperationException("修改数据格式无效");
        }
    }

    /// <summary>
    /// 应用人员修改
    /// </summary>
    private async Task ApplyPersonnelModificationAsync(ApprovalRequest request)
    {
        var personnel = await _context.Personnel
            .FirstOrDefaultAsync(p => p.Id == request.TargetEntityId);

        if (personnel == null)
            throw new InvalidOperationException("目标人员记录不存在");

        try
        {
            var changes = JsonSerializer.Deserialize<PersonnelModificationChanges>(request.RequestedChanges);
            if (changes != null)
            {
                if (!string.IsNullOrEmpty(changes.Name))
                    personnel.Name = changes.Name;
                if (!string.IsNullOrEmpty(changes.Position))
                    personnel.Position = changes.Position;
                if (!string.IsNullOrEmpty(changes.Rank))
                    personnel.Rank = changes.Rank;
                // 其他字段可以根据需要添加
            }
        }
        catch (JsonException)
        {
            throw new InvalidOperationException("修改数据格式无效");
        }
    }
}

/// <summary>
/// 上报修改变更数据
/// </summary>
internal class ReportModificationChanges
{
    public decimal? ActualCompletion { get; set; }
}

/// <summary>
/// 配额修改变更数据
/// </summary>
internal class AllocationModificationChanges
{
    public string? Category { get; set; }
    public string? MaterialName { get; set; }
    public string? Unit { get; set; }
    public decimal? TotalQuota { get; set; }
}

/// <summary>
/// 人员修改变更数据
/// </summary>
internal class PersonnelModificationChanges
{
    public string? Name { get; set; }
    public string? Position { get; set; }
    public string? Rank { get; set; }
}
