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

namespace SolutionErp.Api.Controllers;

[ApiController]
[Route("api/purchase-evaluations")]
[Authorize]
public class PurchaseEvaluationsController(IMediator mediator) : ControllerBase
{
    [HttpGet]
    public async Task<ActionResult<PagedResult<PurchaseEvaluationListItemDto>>> List(
        [FromQuery] int page = 1, [FromQuery] int pageSize = 20,
        [FromQuery] string? search = null, [FromQuery] bool sortDesc = true,
        [FromQuery] PurchaseEvaluationType? type = null,
        [FromQuery] PurchaseEvaluationPhase? phase = null,
        [FromQuery] Guid? projectId = null,
        CancellationToken ct = default)
        => Ok(await mediator.Send(new ListPurchaseEvaluationsQuery(type, phase, projectId)
        { Page = page, PageSize = pageSize, Search = search, SortDesc = sortDesc }, ct));

    [HttpGet("inbox")]
    public async Task<ActionResult<List<PurchaseEvaluationListItemDto>>> Inbox(
        [FromQuery] PurchaseEvaluationType? type = null, CancellationToken ct = default)
        => Ok(await mediator.Send(new GetMyPurchaseEvaluationInboxQuery(type), ct));

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

    [HttpPost]
    public async Task<ActionResult<object>> Create([FromBody] CreatePurchaseEvaluationCommand 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] UpdatePurchaseEvaluationDraftCommand 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] TransitionPeBody body, CancellationToken ct)
    {
        await mediator.Send(new TransitionPurchaseEvaluationCommand(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 DeletePurchaseEvaluationCommand(id), ct);
        return NoContent();
    }

    // ========== Suppliers (N:M) ==========

    [HttpPost("{id:guid}/suppliers")]
    public async Task<ActionResult<object>> AddSupplier(Guid id, [FromBody] AddSupplierBody body, CancellationToken ct)
    {
        var newId = await mediator.Send(new AddPurchaseEvaluationSupplierCommand(
            id, body.SupplierId, body.DisplayName, body.ContactName, body.ContactEmail,
            body.ContactPhone, body.PaymentTermText, body.Note), ct);
        return Ok(new { id = newId });
    }

    [HttpPut("{id:guid}/suppliers/{supplierRowId:guid}")]
    public async Task<IActionResult> UpdateSupplier(Guid id, Guid supplierRowId, [FromBody] AddSupplierBody body, CancellationToken ct)
    {
        await mediator.Send(new UpdatePurchaseEvaluationSupplierCommand(
            id, supplierRowId, body.DisplayName, body.ContactName, body.ContactEmail,
            body.ContactPhone, body.PaymentTermText, body.Note), ct);
        return NoContent();
    }

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

    [HttpPost("{id:guid}/select-winner")]
    public async Task<IActionResult> SelectWinner(Guid id, [FromBody] SelectWinnerBody body, CancellationToken ct)
    {
        await mediator.Send(new SelectPurchaseEvaluationWinnerCommand(id, body.SupplierId), ct);
        return NoContent();
    }

    // ========== Details (hạng mục + ngân sách) ==========

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

    [HttpPut("{id:guid}/details/{detailId:guid}")]
    public async Task<IActionResult> UpdateDetail(Guid id, Guid detailId, [FromBody] DetailBody body, CancellationToken ct)
    {
        await mediator.Send(new UpdatePurchaseEvaluationDetailCommand(
            id, detailId, body.GroupCode, body.GroupName, body.ItemCode, body.NoiDung, body.DonViTinh,
            body.KhoiLuongNganSach, body.KhoiLuongThiCong, body.DonGiaNganSach,
            body.ThanhTienNganSach, 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 DeletePurchaseEvaluationDetailCommand(id, detailId), ct);
        return NoContent();
    }

    // ========== Quotes (báo giá per NCC per Detail) ==========

    [HttpPost("{id:guid}/quotes")]
    public async Task<ActionResult<object>> UpsertQuote(Guid id, [FromBody] QuoteBody body, CancellationToken ct)
    {
        var qid = await mediator.Send(new UpsertPurchaseEvaluationQuoteCommand(
            id, body.PurchaseEvaluationDetailId, body.PurchaseEvaluationSupplierId,
            body.BgVat, body.ChuaVat, body.ThanhTien, body.IsSelected, body.Note), ct);
        return Ok(new { id = qid });
    }

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

    // ========== Changelogs ==========

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

    // ========== Attachments (per-supplier hoặc general) ==========

    // Upload file đính kèm — gắn với NCC cụ thể (supplierRowId) hoặc phiếu tổng.
    [HttpPost("{id:guid}/attachments")]
    [RequestSizeLimit(25_000_000)]
    public async Task<ActionResult<PurchaseEvaluationAttachmentDto>> UploadAttachment(
        Guid id,
        IFormFile file,
        [FromForm] Guid? supplierRowId = null,
        [FromForm] PurchaseEvaluationAttachmentPurpose purpose = PurchaseEvaluationAttachmentPurpose.QuoteDocument,
        [FromForm] string? note = null,
        CancellationToken ct = default)
    {
        if (file is null || file.Length == 0)
            return BadRequest(new { detail = "Chưa chọn file." });

        await using var stream = file.OpenReadStream();
        var dto = await mediator.Send(new UploadPurchaseEvaluationAttachmentCommand(
            id, supplierRowId, file.FileName, file.ContentType, file.Length, stream, purpose, note), ct);
        return Ok(dto);
    }

    [HttpGet("{id:guid}/attachments/{attId:guid}/download")]
    public async Task<IActionResult> DownloadAttachment(Guid id, Guid attId, CancellationToken ct)
    {
        var f = await mediator.Send(new DownloadPurchaseEvaluationAttachmentQuery(id, attId), ct);
        return File(f.Content, f.ContentType, f.FileName);
    }

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

    // ========== Kế thừa HĐ ==========

    // List phiếu đã DaDuyet chưa gen HĐ — dùng cho modal "Tạo HĐ từ phiếu"
    [HttpGet("approved-pending-contract")]
    public async Task<List<PurchaseEvaluationListItemDto>> ListApproved(CancellationToken ct)
        => await mediator.Send(new ListApprovedPurchaseEvaluationsQuery(), ct);

    [HttpPost("{id:guid}/create-contract")]
    public async Task<ActionResult<object>> CreateContractFromEvaluation(
        Guid id, [FromBody] CreateContractFromEvaluationBody body, CancellationToken ct)
    {
        var contractId = await mediator.Send(new CreateContractFromEvaluationCommand(
            id, body.ContractType, body.TenHopDong, body.BypassProcurementAndCCM), ct);
        return Ok(new { contractId });
    }

    // ========== Ý kiến 4 phòng ban ==========

    // Upsert opinion (Add nếu chưa có, Update text + optional sign).
    [HttpPost("{id:guid}/opinions")]
    public async Task<ActionResult<object>> UpsertOpinion(
        Guid id, [FromBody] OpinionBody body, CancellationToken ct)
    {
        var resultId = await mediator.Send(new UpsertPeDepartmentOpinionCommand(
            id, body.Kind, body.Opinion, body.Sign), ct);
        return Ok(new { id = resultId });
    }

    [HttpDelete("{id:guid}/opinions/{kind}")]
    public async Task<IActionResult> DeleteOpinion(Guid id, PeDepartmentKind kind, CancellationToken ct)
    {
        await mediator.Send(new DeletePeDepartmentOpinionCommand(id, kind), ct);
        return NoContent();
    }

    // ========== 2-stage department approvals (Phase 9 — Migration 16) ==========

    // List approvals progress per phase × dept × stage. FE Workflow Panel
    // hiển thị timeline: phase nào đã review/confirm, ai duyệt khi nào.
    [HttpGet("{id:guid}/department-approvals")]
    public async Task<ActionResult<List<PeDepartmentApprovalDto>>> ListDepartmentApprovals(
        Guid id, CancellationToken ct)
        => Ok(await mediator.Send(new ListPeDepartmentApprovalsQuery(id), ct));
}

public record OpinionBody(PeDepartmentKind Kind, string? Opinion, bool Sign);

public record CreateContractFromEvaluationBody(
    Domain.Contracts.ContractType ContractType,
    string? TenHopDong,
    bool BypassProcurementAndCCM = false);

public record TransitionPeBody(PurchaseEvaluationPhase TargetPhase, ApprovalDecision Decision, string? Comment);

public record AddSupplierBody(
    Guid SupplierId,
    string? DisplayName, string? ContactName, string? ContactEmail, string? ContactPhone,
    string? PaymentTermText, string? Note);

public record SelectWinnerBody(Guid SupplierId);

public record DetailBody(
    string GroupCode, string GroupName, string? ItemCode, string NoiDung, string? DonViTinh,
    decimal KhoiLuongNganSach, decimal KhoiLuongThiCong, decimal DonGiaNganSach,
    decimal ThanhTienNganSach, string? GhiChu);

public record QuoteBody(
    Guid PurchaseEvaluationDetailId, Guid PurchaseEvaluationSupplierId,
    decimal BgVat, decimal ChuaVat, decimal ThanhTien, bool IsSelected, string? Note);
