using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using MilitaryTrainingManagement.Data;
using MilitaryTrainingManagement.Models.Entities;
using MilitaryTrainingManagement.Models.Enums;
using MilitaryTrainingManagement.Services.Interfaces;

namespace MilitaryTrainingManagement.Controllers;

/// <summary>
/// 消耗记录删改申请控制器
/// </summary>
[Authorize]
public class ConsumptionChangeRequestsController : BaseApiController
{
    private readonly ApplicationDbContext _context;
    private readonly ILogger<ConsumptionChangeRequestsController> _logger;
    private readonly IAuditService _auditService;

    public ConsumptionChangeRequestsController(
        ApplicationDbContext context,
        ILogger<ConsumptionChangeRequestsController> logger,
        IAuditService auditService)
    {
        _context = context;
        _logger = logger;
        _auditService = auditService;
    }
    
    private string? GetClientIpAddress()
    {
        return HttpContext.Connection.RemoteIpAddress?.ToString();
    }

    /// <summary>
    /// 创建删改申请
    /// </summary>
    [HttpPost]
    public async Task<IActionResult> Create([FromBody] CreateChangeRequestDto request)
    {
        var unitId = GetCurrentUnitId();
        var userId = GetCurrentUserId();
        if (unitId == null || userId == null)
            return Unauthorized();

        // 验证消耗记录存在且属于当前单位
        var report = await _context.ConsumptionReports
            .Include(r => r.ReportedByUnit)
            .Include(r => r.AllocationDistribution)
                .ThenInclude(d => d.Allocation)
            .FirstOrDefaultAsync(r => r.Id == request.ConsumptionReportId);

        if (report == null)
            return NotFound(new { message = "消耗记录不存在" });

        if (report.ReportedByUnitId != unitId.Value)
            return BadRequest(new { message = "只能申请删改本单位的上报记录" });

        // 检查是否已有待处理的申请
        var existingRequest = await _context.ConsumptionReportChangeRequests
            .AnyAsync(r => r.ConsumptionReportId == request.ConsumptionReportId 
                && r.Status == ChangeRequestStatus.Pending);

        if (existingRequest)
            return BadRequest(new { message = "该记录已有待处理的删改申请" });

        var changeRequest = new ConsumptionReportChangeRequest
        {
            ConsumptionReportId = request.ConsumptionReportId,
            RequestType = request.RequestType,
            Reason = request.Reason,
            Status = ChangeRequestStatus.Pending,
            RequestedByUnitId = unitId.Value,
            RequestedByUserId = userId.Value,
            RequestedAt = DateTime.UtcNow
        };

        _context.ConsumptionReportChangeRequests.Add(changeRequest);
        await _context.SaveChangesAsync();

        _logger.LogInformation("单位 {UnitId} 创建了消耗记录 {ReportId} 的{Type}申请",
            unitId, request.ConsumptionReportId, request.RequestType);

        // 记录审计日志
        var requestTypeName = request.RequestType == ChangeRequestType.Delete ? "删除" : "修改";
        var materialName = report.AllocationDistribution?.Allocation?.MaterialName ?? "未知物资";
        
        await _auditService.LogApprovalAsync(
            "ConsumptionReportChangeRequest",
            changeRequest.Id,
            "Create",
            $"提交消耗记录{requestTypeName}申请，物资：{materialName}，申请原因：{request.Reason}",
            userId,
            unitId,
            GetClientIpAddress());

        return Ok(new { message = "申请已提交", id = changeRequest.Id });
    }

    /// <summary>
    /// 获取待处理的申请列表（上级单位查看下级的申请）
    /// </summary>
    [HttpGet("pending")]
    public async Task<IActionResult> GetPendingRequests()
    {
        var unitId = GetCurrentUnitId();
        if (unitId == null)
            return Unauthorized();

        // 获取下级单位的ID列表
        var subordinateIds = await GetSubordinateUnitIds(unitId.Value);

        var requests = await _context.ConsumptionReportChangeRequests
            .Include(r => r.ConsumptionReport)
                .ThenInclude(cr => cr.AllocationDistribution)
                    .ThenInclude(d => d.Allocation)
            .Include(r => r.RequestedByUnit)
            .Include(r => r.RequestedByUser)
            .Where(r => r.Status == ChangeRequestStatus.Pending 
                && subordinateIds.Contains(r.RequestedByUnitId))
            .OrderByDescending(r => r.RequestedAt)
            .Select(r => new
            {
                r.Id,
                r.ConsumptionReportId,
                RequestType = r.RequestType.ToString(),
                r.Reason,
                Status = r.Status.ToString(),
                r.RequestedAt,
                RequestedByUnitName = r.RequestedByUnit.Name,
                RequestedByUserName = r.RequestedByUser.DisplayName,
                ConsumptionReport = new
                {
                    r.ConsumptionReport.Id,
                    r.ConsumptionReport.ReportedAmount,
                    r.ConsumptionReport.ReportedAt,
                    r.ConsumptionReport.Remarks,
                    MaterialName = r.ConsumptionReport.AllocationDistribution.Allocation.MaterialName,
                    Unit = r.ConsumptionReport.AllocationDistribution.Allocation.Unit
                }
            })
            .ToListAsync();

        return Ok(requests);
    }

    /// <summary>
    /// 获取本单位的申请列表
    /// </summary>
    [HttpGet("my")]
    public async Task<IActionResult> GetMyRequests()
    {
        var unitId = GetCurrentUnitId();
        if (unitId == null)
            return Unauthorized();

        var requests = await _context.ConsumptionReportChangeRequests
            .Include(r => r.ConsumptionReport)
            .Include(r => r.ProcessedByUnit)
            .Where(r => r.RequestedByUnitId == unitId.Value)
            .OrderByDescending(r => r.RequestedAt)
            .Select(r => new
            {
                r.Id,
                r.ConsumptionReportId,
                RequestType = r.RequestType.ToString(),
                r.Reason,
                Status = r.Status.ToString(),
                r.RequestedAt,
                r.ProcessedAt,
                ProcessedByUnitName = r.ProcessedByUnit != null ? r.ProcessedByUnit.Name : null,
                r.ProcessComments
            })
            .ToListAsync();

        return Ok(requests);
    }

    /// <summary>
    /// 获取已处理的申请列表（上级单位已处理的下级申请）
    /// </summary>
    [HttpGet("processed")]
    public async Task<IActionResult> GetProcessedRequests()
    {
        var unitId = GetCurrentUnitId();
        if (unitId == null)
            return Unauthorized();

        // 获取下级单位的ID列表
        var subordinateIds = await GetSubordinateUnitIds(unitId.Value);

        var requests = await _context.ConsumptionReportChangeRequests
            .Include(r => r.ConsumptionReport)
                .ThenInclude(cr => cr.AllocationDistribution)
                    .ThenInclude(d => d.Allocation)
            .Include(r => r.RequestedByUnit)
            .Include(r => r.RequestedByUser)
            .Include(r => r.ProcessedByUnit)
            .Where(r => r.Status != ChangeRequestStatus.Pending 
                && subordinateIds.Contains(r.RequestedByUnitId))
            .OrderByDescending(r => r.ProcessedAt)
            .Select(r => new
            {
                r.Id,
                r.ConsumptionReportId,
                RequestType = r.RequestType.ToString(),
                r.Reason,
                Status = r.Status.ToString(),
                r.RequestedAt,
                RequestedByUnitName = r.RequestedByUnit.Name,
                RequestedByUserName = r.RequestedByUser.DisplayName,
                r.ProcessedAt,
                ProcessedByUnitName = r.ProcessedByUnit != null ? r.ProcessedByUnit.Name : null,
                r.ProcessComments,
                ConsumptionReport = new
                {
                    r.ConsumptionReport.Id,
                    r.ConsumptionReport.ReportedAmount,
                    r.ConsumptionReport.ReportedAt,
                    r.ConsumptionReport.Remarks,
                    MaterialName = r.ConsumptionReport.AllocationDistribution.Allocation.MaterialName,
                    Unit = r.ConsumptionReport.AllocationDistribution.Allocation.Unit
                }
            })
            .ToListAsync();

        return Ok(requests);
    }

    /// <summary>
    /// 处理申请（同意或拒绝）
    /// </summary>
    [HttpPost("{id}/process")]
    public async Task<IActionResult> ProcessRequest(int id, [FromBody] ProcessChangeRequestDto request)
    {
        var unitId = GetCurrentUnitId();
        var userId = GetCurrentUserId();
        if (unitId == null || userId == null)
            return Unauthorized();

        var changeRequest = await _context.ConsumptionReportChangeRequests
            .Include(r => r.ConsumptionReport)
                .ThenInclude(cr => cr.AllocationDistribution)
                    .ThenInclude(d => d.Allocation)
            .Include(r => r.RequestedByUnit)
            .FirstOrDefaultAsync(r => r.Id == id);

        if (changeRequest == null)
            return NotFound(new { message = "申请不存在" });

        if (changeRequest.Status != ChangeRequestStatus.Pending)
            return BadRequest(new { message = "该申请已处理" });

        // 验证是否有权限处理（必须是申请单位的上级）
        var isParent = await IsParentUnit(unitId.Value, changeRequest.RequestedByUnitId);
        if (!isParent)
            return StatusCode(403, new { message = "您没有权限处理此申请" });

        changeRequest.Status = request.Approved ? ChangeRequestStatus.Approved : ChangeRequestStatus.Rejected;
        changeRequest.ProcessedByUnitId = unitId.Value;
        changeRequest.ProcessedByUserId = userId.Value;
        changeRequest.ProcessedAt = DateTime.UtcNow;
        changeRequest.ProcessComments = request.Comments;

        // 如果同意删除，执行删除操作
        if (request.Approved && changeRequest.RequestType == ChangeRequestType.Delete)
        {
            var report = changeRequest.ConsumptionReport;
            var distribution = report.AllocationDistribution;

            // 更新分配的实际完成数量
            distribution.ActualCompletion -= report.ReportedAmount;
            if (distribution.ActualCompletion < 0)
                distribution.ActualCompletion = 0;

            // 删除消耗记录
            _context.ConsumptionReports.Remove(report);

            _logger.LogInformation("消耗记录 {ReportId} 已被删除，分配 {DistributionId} 的实际完成数量已更新",
                report.Id, distribution.Id);
        }

        await _context.SaveChangesAsync();

        var action = request.Approved ? "同意" : "拒绝";
        _logger.LogInformation("单位 {UnitId} {Action}了消耗记录删改申请 {RequestId}",
            unitId, action, id);

        // 记录审计日志
        var requestTypeName = changeRequest.RequestType == ChangeRequestType.Delete ? "删除" : "修改";
        var materialName = changeRequest.ConsumptionReport?.AllocationDistribution?.Allocation?.MaterialName ?? "未知物资";
        var reportedByUnitName = changeRequest.RequestedByUnit?.Name ?? "未知单位";
        
        await _auditService.LogApprovalAsync(
            "ConsumptionReportChangeRequest",
            id,
            request.Approved ? "Approve" : "Reject",
            $"{action}「{reportedByUnitName}」的消耗记录{requestTypeName}申请，物资：{materialName}，原因：{changeRequest.Reason}，处理意见：{request.Comments ?? "无"}",
            userId,
            unitId,
            GetClientIpAddress());

        return Ok(new { message = $"已{action}该申请" });
    }

    /// <summary>
    /// 修改消耗记录（上级单位在同意修改申请后执行）
    /// </summary>
    [HttpPost("{id}/modify")]
    public async Task<IActionResult> ModifyReport(int id, [FromBody] ModifyReportDto request)
    {
        var unitId = GetCurrentUnitId();
        if (unitId == null)
            return Unauthorized();

        var changeRequest = await _context.ConsumptionReportChangeRequests
            .Include(r => r.ConsumptionReport)
                .ThenInclude(cr => cr.AllocationDistribution)
                    .ThenInclude(d => d.Allocation)
            .FirstOrDefaultAsync(r => r.Id == id);

        if (changeRequest == null)
            return NotFound(new { message = "申请不存在" });

        if (changeRequest.Status != ChangeRequestStatus.Approved)
            return BadRequest(new { message = "只能修改已同意的申请" });

        if (changeRequest.RequestType != ChangeRequestType.Modify)
            return BadRequest(new { message = "该申请不是修改类型" });

        // 验证是否有权限（必须是处理单位）
        if (changeRequest.ProcessedByUnitId != unitId.Value)
            return StatusCode(403, new { message = "只有处理单位才能修改" });

        var report = changeRequest.ConsumptionReport;
        var distribution = report.AllocationDistribution;
        var oldAmount = report.ReportedAmount;

        // 更新消耗记录
        report.ReportedAmount = request.NewAmount;
        report.Remarks = request.NewRemarks ?? report.Remarks;

        // 更新分配的实际完成数量
        distribution.ActualCompletion = distribution.ActualCompletion - oldAmount + request.NewAmount;

        await _context.SaveChangesAsync();

        _logger.LogInformation("消耗记录 {ReportId} 已被修改，数量从 {OldAmount} 改为 {NewAmount}",
            report.Id, oldAmount, request.NewAmount);

        // 记录审计日志
        var userId = GetCurrentUserId();
        var materialName = distribution.Allocation?.MaterialName ?? "未知物资";
        
        await _auditService.LogApprovalAsync(
            "ConsumptionReport",
            report.Id,
            "Update",
            $"修改消耗记录，物资：{materialName}，数量从 {oldAmount} 改为 {request.NewAmount}",
            userId,
            unitId,
            GetClientIpAddress());

        return Ok(new { message = "修改成功" });
    }

    /// <summary>
    /// 检查消耗记录是否有待处理的申请
    /// </summary>
    [HttpGet("check/{consumptionReportId}")]
    public async Task<IActionResult> CheckPendingRequest(int consumptionReportId)
    {
        var hasPending = await _context.ConsumptionReportChangeRequests
            .AnyAsync(r => r.ConsumptionReportId == consumptionReportId 
                && r.Status == ChangeRequestStatus.Pending);

        return Ok(new { hasPendingRequest = hasPending });
    }

    private async Task<List<int>> GetSubordinateUnitIds(int unitId)
    {
        var result = new List<int>();
        var children = await _context.OrganizationalUnits
            .Where(u => u.ParentId == unitId)
            .Select(u => u.Id)
            .ToListAsync();

        foreach (var childId in children)
        {
            result.Add(childId);
            var grandChildren = await GetSubordinateUnitIds(childId);
            result.AddRange(grandChildren);
        }

        return result;
    }

    private async Task<bool> IsParentUnit(int parentUnitId, int childUnitId)
    {
        var childUnit = await _context.OrganizationalUnits
            .FirstOrDefaultAsync(u => u.Id == childUnitId);

        if (childUnit == null) return false;

        var currentParentId = childUnit.ParentId;
        while (currentParentId.HasValue)
        {
            if (currentParentId.Value == parentUnitId)
                return true;

            var parent = await _context.OrganizationalUnits
                .FirstOrDefaultAsync(u => u.Id == currentParentId.Value);
            currentParentId = parent?.ParentId;
        }

        return false;
    }
}

public class CreateChangeRequestDto
{
    public int ConsumptionReportId { get; set; }
    public ChangeRequestType RequestType { get; set; }
    public string Reason { get; set; } = string.Empty;
}

public class ProcessChangeRequestDto
{
    public bool Approved { get; set; }
    public string? Comments { get; set; }
}

public class ModifyReportDto
{
    public decimal NewAmount { get; set; }
    public string? NewRemarks { get; set; }
}
