using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SolutionErp.Application.Budgets;
using SolutionErp.Application.Budgets.Dtos;
using SolutionErp.Application.Common.Models;
using SolutionErp.Domain.Budgets;
using SolutionErp.Domain.Contracts;

namespace SolutionErp.Api.Controllers;

[ApiController]
[Route("api/budgets")]
[Authorize]
public class BudgetsController(IMediator mediator) : ControllerBase
{
    [HttpGet]
    public async Task<ActionResult<PagedResult<BudgetListItemDto>>> List(
        [FromQuery] int page = 1, [FromQuery] int pageSize = 20,
        [FromQuery] string? search = null, [FromQuery] bool sortDesc = true,
        [FromQuery] BudgetPhase? phase = null,
        [FromQuery] Guid? projectId = null,
        [FromQuery] int? namNganSach = null,
        CancellationToken ct = default)
        => Ok(await mediator.Send(new ListBudgetsQuery(phase, projectId, namNganSach)
        { Page = page, PageSize = pageSize, Search = search, SortDesc = sortDesc }, ct));

    [HttpGet("{id:guid}")]
    public async Task<ActionResult<BudgetDetailBundleDto>> Get(Guid id, CancellationToken ct)
        => Ok(await mediator.Send(new GetBudgetQuery(id), ct));

    [HttpPost]
    public async Task<ActionResult<object>> Create([FromBody] CreateBudgetCommand cmd, CancellationToken ct)
    {
        var id = await mediator.Send(cmd, ct);
        return CreatedAtAction(nameof(Get), new { id }, new { id });
    }

    [HttpPut("{id:guid}")]
    public async Task<IActionResult> Update(Guid id, [FromBody] UpdateBudgetDraftCommand cmd, CancellationToken ct)
    {
        if (id != cmd.Id) return BadRequest(new { detail = "ID không khớp" });
        await mediator.Send(cmd, ct);
        return NoContent();
    }

    [HttpPost("{id:guid}/transitions")]
    public async Task<IActionResult> Transition(Guid id, [FromBody] TransitionBudgetBody body, CancellationToken ct)
    {
        await mediator.Send(new TransitionBudgetCommand(id, body.TargetPhase, body.Decision, body.Comment), ct);
        return NoContent();
    }

    [HttpDelete("{id:guid}")]
    public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
    {
        await mediator.Send(new DeleteBudgetCommand(id), ct);
        return NoContent();
    }

    [HttpPost("{id:guid}/details")]
    public async Task<ActionResult<object>> AddDetail(Guid id, [FromBody] BudgetDetailBody body, CancellationToken ct)
    {
        var newId = await mediator.Send(new AddBudgetDetailCommand(
            id, body.GroupCode, body.GroupName, body.ItemCode, body.NoiDung, body.DonViTinh,
            body.KhoiLuong, body.DonGia, body.ThanhTien, body.GhiChu), ct);
        return Ok(new { id = newId });
    }

    [HttpPut("{id:guid}/details/{detailId:guid}")]
    public async Task<IActionResult> UpdateDetail(Guid id, Guid detailId, [FromBody] BudgetDetailBody body, CancellationToken ct)
    {
        await mediator.Send(new UpdateBudgetDetailCommand(
            id, detailId, body.GroupCode, body.GroupName, body.ItemCode, body.NoiDung, body.DonViTinh,
            body.KhoiLuong, body.DonGia, body.ThanhTien, body.GhiChu), ct);
        return NoContent();
    }

    [HttpDelete("{id:guid}/details/{detailId:guid}")]
    public async Task<IActionResult> DeleteDetail(Guid id, Guid detailId, CancellationToken ct)
    {
        await mediator.Send(new DeleteBudgetDetailCommand(id, detailId), ct);
        return NoContent();
    }

    [HttpGet("{id:guid}/changelogs")]
    public async Task<List<BudgetChangelogDto>> GetChangelogs(Guid id, CancellationToken ct)
        => await mediator.Send(new ListBudgetChangelogsQuery(id), ct);

    // 2-stage department approval list (Phase 9 — Migration 16).
    [HttpGet("{id:guid}/department-approvals")]
    public async Task<ActionResult<List<BudgetDepartmentApprovalDto>>> ListDepartmentApprovals(
        Guid id, CancellationToken ct)
        => Ok(await mediator.Send(new ListBudgetDepartmentApprovalsQuery(id), ct));
}

public record TransitionBudgetBody(BudgetPhase TargetPhase, ApprovalDecision Decision, string? Comment);
public record BudgetDetailBody(
    string GroupCode, string GroupName, string? ItemCode, string NoiDung,
    string? DonViTinh, decimal KhoiLuong, decimal DonGia, decimal ThanhTien, string? GhiChu);
