// Panel 3: workflow timeline + transition buttons + approval history + changelog.
// Pulls nextPhases từ BE bundle (single source of truth) → render per-phase
// action button. Approvals + History moved here from PeDetailTabs (2 section
// dưới cùng) để Panel 2 tập trung hiển thị nội dung phiếu (Info + NCC + Items).
import { useState } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { toast } from 'sonner'
import { Dialog } from '@/components/ui/Dialog'
import { Button } from '@/components/ui/Button'
import { Label } from '@/components/ui/Label'
import { Textarea } from '@/components/ui/Textarea'
import { api } from '@/lib/api'
import { getErrorMessage } from '@/lib/apiError'
import { cn } from '@/lib/cn'
import { useAuth } from '@/contexts/AuthContext'
import {
  ApprovalStage,
  PurchaseEvaluationPhase,
  PurchaseEvaluationPhaseColor,
  PurchaseEvaluationPhaseLabel,
  WorkflowReturnMode,
  type PeDepartmentApproval,
  type PeDetailBundle,
} from '@/types/purchaseEvaluation'
import { PeApprovalsSection, PeHistorySection } from './PeDetailTabs'

export function PeWorkflowPanel({
  evaluation,
  readOnly = false,
}: {
  evaluation: PeDetailBundle
  /** true = ẩn Chuyển tiếp + Dialog transition (dùng cho Danh sách, không dùng Duyệt). */
  readOnly?: boolean
}) {
  const [target, setTarget] = useState<number | null>(null)
  const [comment, setComment] = useState('')
  // Mig 28 (S21 t4) — F1 mode Trả lại. Default Drafter (backward compat S17).
  const [returnMode, setReturnMode] = useState<WorkflowReturnMode>(WorkflowReturnMode.Drafter)
  const [returnTargetUserId, setReturnTargetUserId] = useState<string | null>(null)
  const qc = useQueryClient()
  const { user: currentUser } = useAuth()
  const isAdmin = currentUser?.roles?.includes('Admin') ?? false

  // Mig 29 (S21 t5) — F1 options per-Level (Cấp Approver hiện tại). Null nếu
  // V1 legacy hoặc pointer chưa init → fallback chỉ "Trả về Drafter".
  const levelOptions = evaluation.currentLevelOptions
  // List approvers đã ký (cho mode Assignee dropdown pick)
  const signedApprovers = (evaluation.levelOpinions ?? [])
    .map(o => ({ userId: o.approverUserId, fullName: o.approverFullName ?? 'NV' }))
    // Dedupe by userId (1 NV có thể ký nhiều cấp nếu workflow đặt như vậy)
    .filter((v, i, arr) => arr.findIndex(x => x.userId === v.userId) === i)

  // Mig 24 — V2 schema chỉ cho phép approver trong CurrentApproval.approvers
  // thao tác cấp hiện tại. UAT S22+1: disable cả 3 button (Duyệt + Trả lại
  // + Từ chối) khi actor không match. BE mirror EnsureCanRejectV2Async.
  // Admin bypass.
  const v2Approvers = evaluation.currentApproval?.approvers ?? []
  const actorInV2Level = isAdmin
    || (currentUser?.id && v2Approvers.some(a => a.userId === currentUser.id))
  const isV2Pending = !!evaluation.currentApproval
  const blockedByV2Level = isV2Pending && !actorInV2Level

  // 2-stage dept approvals (Migration 16) — fetch riêng để FE Workflow Panel
  // hiển thị progress per phase × dept (Stage Review NV / Confirm TPB).
  const { data: deptApprovals = [] } = useQuery<PeDepartmentApproval[]>({
    queryKey: ['pe-dept-approvals', evaluation.id],
    queryFn: async () => {
      const r = await api.get(`/purchase-evaluations/${evaluation.id}/department-approvals`)
      return r.data
    },
  })

  const transition = useMutation({
    mutationFn: async () => {
      // Decision = Reject (2) khi:
      //  - target = TuChoi (huỷ phiếu)
      //  - target = DangSoanThao từ phase trung gian (= Trả lại legacy Mig 16
      //    set RejectedFromPhase + clear N-stage rows + Drafter resume jump-back)
      //  - target = TraLai (98) từ phase trung gian — Session 17 spec mới: Trả
      //    lại là Phase RIÊNG (gotcha #45 — thiếu nhánh này gây "Trả về nhưng
      //    hệ thống vẫn duyệt" do BE nhận decision=Approve → ApproveV2Async).
      // BE có guard mirror trong PurchaseEvaluationWorkflowService.TransitionAsync
      // throw ConflictException nếu payload mismatch — phải sync 2 phía.
      const isReject = target === PurchaseEvaluationPhase.TuChoi
        || (target === PurchaseEvaluationPhase.DangSoanThao
            && evaluation.phase !== PurchaseEvaluationPhase.DangSoanThao)
        || (target === PurchaseEvaluationPhase.TraLai
            && evaluation.phase !== PurchaseEvaluationPhase.TraLai)
      // Mig 28 (S21 t4) — F1: chỉ gửi returnMode khi target=TraLai + mode != null
      const isTraLaiAction = target === PurchaseEvaluationPhase.TraLai
        && evaluation.phase !== PurchaseEvaluationPhase.TraLai
      return api.post(`/purchase-evaluations/${evaluation.id}/transitions`, {
        targetPhase: target,
        decision: isReject ? 2 : 1,
        comment: comment || null,
        returnMode: isTraLaiAction ? returnMode : null,
        returnTargetUserId: isTraLaiAction && returnMode === WorkflowReturnMode.Assignee
          ? returnTargetUserId : null,
      })
    },
    onSuccess: () => {
      toast.success('Đã chuyển phase.')
      qc.invalidateQueries({ queryKey: ['pe-detail', evaluation.id] })
      qc.invalidateQueries({ queryKey: ['pe-list'] })
      qc.invalidateQueries({ queryKey: ['pe-dept-approvals', evaluation.id] })
      setTarget(null)
      setComment('')
      setReturnMode(WorkflowReturnMode.Drafter)
      setReturnTargetUserId(null)
    },
    onError: e => toast.error(getErrorMessage(e)),
  })

  const next = evaluation.workflow.nextPhases
  const flow = evaluation.approvalFlow

  return (
    <div className="space-y-4">
      <div>
        <h3 className="text-sm font-semibold text-slate-900">Quy trình duyệt</h3>
        {evaluation.approvalWorkflowCode && (
          <p className="mt-0.5 font-mono text-[11px] text-slate-500">
            {evaluation.approvalWorkflowCode} v{String(evaluation.approvalWorkflowVersion ?? 0).padStart(2, '0')}
            {evaluation.approvalWorkflowName && <> · <span className="font-sans">{evaluation.approvalWorkflowName}</span></>}
          </p>
        )}
      </div>

      {/* Mig 24 V2 — Flow render Bước → Cấp → NV thay phase cards.
          Status: Done (✓ emerald) / Current (● brand) / Pending (○ slate) */}
      {flow && flow.steps.length > 0 && (
        <ol className="space-y-2">
          {flow.steps.map(step => {
            const stepIcon = step.status === 'Done' ? '✓' : step.status === 'Current' ? '●' : '○'
            return (
              <li
                key={step.order}
                className={cn(
                  'rounded-md border p-2',
                  step.status === 'Current' && 'border-brand-300 bg-brand-50/50',
                  step.status === 'Done' && 'border-emerald-200 bg-emerald-50/40',
                  step.status === 'Pending' && 'border-slate-200 bg-white',
                )}
              >
                <div className="flex items-center gap-2 text-xs font-medium">
                  <span className={cn(
                    'flex h-5 w-5 shrink-0 items-center justify-center rounded-full font-bold',
                    step.status === 'Done' && 'bg-emerald-500 text-white',
                    step.status === 'Current' && 'bg-brand-600 text-white',
                    step.status === 'Pending' && 'bg-slate-200 text-slate-500',
                  )}>
                    {stepIcon}
                  </span>
                  <span className="text-slate-800">Bước {step.order} — {step.name}</span>
                  {step.departmentName && (
                    <span className="rounded bg-emerald-50 px-1.5 py-0.5 text-[10px] font-medium text-emerald-700">
                      {step.departmentName}
                    </span>
                  )}
                </div>
                {step.levels.length > 0 && (
                  <ul className="mt-1.5 ml-7 space-y-1 border-l-2 border-violet-200 pl-2">
                    {step.levels.map(lv => {
                      const lvIcon = lv.status === 'Done' ? '✓' : lv.status === 'Current' ? '●' : '○'
                      return (
                        <li key={lv.order} className="text-[11px]">
                          <div className="flex items-start gap-1.5">
                            <span className={cn(
                              'mt-0.5 inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-[9px] font-bold',
                              lv.status === 'Done' && 'bg-emerald-500 text-white',
                              lv.status === 'Current' && 'bg-brand-600 text-white',
                              lv.status === 'Pending' && 'bg-slate-200 text-slate-500',
                            )}>
                              {lvIcon}
                            </span>
                            <div className="min-w-0 flex-1">
                              <div className="font-medium text-slate-700">
                                {lv.name || `Cấp ${lv.order}`}
                                {lv.status === 'Current' && <span className="ml-1.5 text-[10px] font-normal text-brand-700">đang chờ</span>}
                                {lv.status === 'Done' && <span className="ml-1.5 text-[10px] font-normal text-emerald-600">đã duyệt</span>}
                              </div>
                              <div className="text-slate-500">
                                {lv.approvers.map(a => a.fullName).join(' / ') || '(chưa cấu hình)'}
                              </div>
                            </div>
                          </div>
                        </li>
                      )
                    })}
                  </ul>
                )}
              </li>
            )
          })}
        </ol>
      )}

      {!flow && (
        <div className="rounded border border-slate-200 bg-slate-50 px-3 py-2 text-[11px] text-slate-600">
          Phiếu này dùng quy trình cũ — workflow chi tiết không khả dụng.
        </div>
      )}

      {/* Mig 24 — V2 banner Bước/Cấp + danh sách NV duyệt */}
      {isV2Pending && evaluation.currentApproval && !readOnly && (
        <div className={cn(
          'rounded border px-3 py-2 text-[11px]',
          actorInV2Level
            ? 'border-emerald-200 bg-emerald-50 text-emerald-800'
            : 'border-amber-300 bg-amber-50 text-amber-800',
        )}>
          <div className="font-medium">
            Đang chờ Bước {evaluation.currentApproval.stepIndex + 1} ({evaluation.currentApproval.stepName})
            {evaluation.currentApproval.stepDepartmentName && <> · {evaluation.currentApproval.stepDepartmentName}</>}
            {' — '}Cấp {evaluation.currentApproval.levelOrder}
          </div>
          <div className="mt-0.5">
            NV duyệt: {evaluation.currentApproval.approvers.map(a => a.fullName).join(' / ') || '(chưa có)'}
          </div>
          {actorInV2Level
            ? <div className="mt-0.5 font-medium">✓ Đến lượt bạn duyệt</div>
            : <div className="mt-0.5">⚠ Không phải lượt bạn — chỉ NV trên mới duyệt được cấp này</div>}
        </div>
      )}

      {next.length > 0 && !readOnly && (
        <div>
          <Label className="text-xs">Hành động:</Label>
          <div className="mt-1 flex flex-wrap gap-1.5">
            {next.map(p => {
              // Phân loại button theo hành động (3 màu khác nhau, in đậm):
              // - Duyệt   = forward phase tiếp theo — emerald (xanh lá positive)
              // - Trả lại = về DangSoanThao/TraLai (từ phase trung gian) — amber (request changes)
              // - Từ chối = TuChoi — red (terminal negative)
              const isSendBack = (p === PurchaseEvaluationPhase.DangSoanThao || p === PurchaseEvaluationPhase.TraLai)
                && evaluation.phase !== PurchaseEvaluationPhase.DangSoanThao
                && evaluation.phase !== PurchaseEvaluationPhase.TraLai
              const isCancel = p === PurchaseEvaluationPhase.TuChoi
              const isForwardApprove = !isSendBack && !isCancel
              // Mig 24 + UAT S22+1 — disable cả 3 button khi actor không match
              // currentLevel.ApproverUserId. "Không quyền = ko quyền mọi hành động."
              const isDisabled = blockedByV2Level
              const label = isSendBack ? '← Trả lại' : isCancel ? '✗ Từ chối' : '✓ Duyệt'
              const title = isDisabled && evaluation.currentApproval
                ? `Cấp ${evaluation.currentApproval.levelOrder} chỉ ${evaluation.currentApproval.approvers.map(a => a.fullName).join(' / ')} mới thao tác được (Duyệt / Trả lại / Từ chối).`
                : isForwardApprove
                  ? `Duyệt → ${PurchaseEvaluationPhaseLabel[p]}`
                  : undefined
              return (
                <button
                  key={p}
                  onClick={() => !isDisabled && setTarget(p)}
                  disabled={isDisabled}
                  title={title}
                  className={cn(
                    'rounded border px-2 py-1 text-[11px] font-bold transition',
                    isDisabled && 'cursor-not-allowed border-slate-200 bg-slate-50 text-slate-400 hover:bg-slate-50',
                    !isDisabled && isForwardApprove && 'border-emerald-300 text-emerald-700 hover:bg-emerald-50',
                    !isDisabled && isSendBack && 'border-amber-300 text-amber-700 hover:bg-amber-50',
                    !isDisabled && isCancel && 'border-red-300 text-red-700 hover:bg-red-50',
                  )}
                >
                  {label}
                </button>
              )
            })}
          </div>
        </div>
      )}
      {readOnly && next.length > 0 && (
        <div className="rounded border border-dashed border-slate-200 px-3 py-2 text-[11px] text-slate-500">
          Vào menu &ldquo;Duyệt&rdquo; để chuyển phase.
        </div>
      )}

      {target !== null && (() => {
        const isCancel = target === PurchaseEvaluationPhase.TuChoi
        // isSendBack sync với button label L205-207 + payload isReject L64-68
        // (gotcha #45). Include cả DangSoanThao (legacy Mig 16) lẫn TraLai
        // (Session 17 spec) — cả 2 là Trả lại Drafter sửa.
        const isSendBack = (target === PurchaseEvaluationPhase.DangSoanThao
                            || target === PurchaseEvaluationPhase.TraLai)
          && evaluation.phase !== PurchaseEvaluationPhase.DangSoanThao
          && evaluation.phase !== PurchaseEvaluationPhase.TraLai
        const dialogTitle = isCancel
          ? '✗ Từ chối phiếu (khoá hoàn toàn)'
          : isSendBack
            ? '← Trả lại Drafter sửa'
            : `✓ Duyệt → ${PurchaseEvaluationPhaseLabel[target]}`
        return (
          <Dialog
            open
            onClose={() => setTarget(null)}
            title={dialogTitle}
            footer={<>
              <Button variant="ghost" onClick={() => setTarget(null)}>Hủy</Button>
              <Button onClick={() => transition.mutate()} disabled={transition.isPending}>Xác nhận</Button>
            </>}
          >
            {isCancel && (
              <div className="mb-3 rounded border border-red-200 bg-red-50 px-3 py-2 text-[11px] text-red-800">
                ⚠ Phiếu sẽ bị khoá hoàn toàn (không edit/transition được nữa). Drafter cần tạo phiếu mới nếu muốn làm lại.
              </div>
            )}
            {isSendBack && (
              <>
                {/* Mig 28 (S21 t4) — F1 mode picker khi Trả lại. Show modes
                    enabled per workflow.options. Default Drafter (S17 fallback). */}
                {(levelOptions?.allowReturnOneLevel
                  || levelOptions?.allowReturnOneStep
                  || levelOptions?.allowReturnToAssignee
                  || levelOptions?.allowReturnToDrafter
                  || !levelOptions) && (
                  <div className="mb-3 space-y-1.5">
                    <Label className="text-[12px]">Chọn cách Trả lại</Label>
                    <div className="space-y-1">
                      {(levelOptions?.allowReturnOneLevel) && (
                        <label className="flex items-start gap-2 rounded border border-amber-200 bg-white px-2 py-1.5 text-[12px] hover:bg-amber-50/40">
                          <input
                            type="radio"
                            className="mt-0.5"
                            checked={returnMode === WorkflowReturnMode.OneLevel}
                            onChange={() => setReturnMode(WorkflowReturnMode.OneLevel)}
                          />
                          <span>
                            <span className="font-medium">Trả về 1 Cấp trước</span>
                            <span className="block text-[10px] text-slate-500">Lùi 1 Cấp trong cùng Bước. NV cấp trước nhận lại.</span>
                          </span>
                        </label>
                      )}
                      {(levelOptions?.allowReturnOneStep) && (
                        <label className="flex items-start gap-2 rounded border border-amber-200 bg-white px-2 py-1.5 text-[12px] hover:bg-amber-50/40">
                          <input
                            type="radio"
                            className="mt-0.5"
                            checked={returnMode === WorkflowReturnMode.OneStep}
                            onChange={() => setReturnMode(WorkflowReturnMode.OneStep)}
                          />
                          <span>
                            <span className="font-medium">Trả về 1 Bước trước</span>
                            <span className="block text-[10px] text-slate-500">Lùi sang Bước trước, NV Cấp cuối Bước đó nhận lại.</span>
                          </span>
                        </label>
                      )}
                      {(levelOptions?.allowReturnToAssignee) && (
                        <label className="flex items-start gap-2 rounded border border-amber-200 bg-white px-2 py-1.5 text-[12px] hover:bg-amber-50/40">
                          <input
                            type="radio"
                            className="mt-0.5"
                            checked={returnMode === WorkflowReturnMode.Assignee}
                            onChange={() => setReturnMode(WorkflowReturnMode.Assignee)}
                          />
                          <span className="flex-1">
                            <span className="font-medium">Trả về Người chỉ định</span>
                            <span className="block text-[10px] text-slate-500">Pick từ list NV đã duyệt trước đó. Workflow set Cấp/Bước của NV.</span>
                            {returnMode === WorkflowReturnMode.Assignee && (
                              <select
                                className="mt-1.5 w-full rounded border border-slate-300 px-2 py-1 text-[12px]"
                                value={returnTargetUserId ?? ''}
                                onChange={e => setReturnTargetUserId(e.target.value || null)}
                              >
                                <option value="">— Chọn NV —</option>
                                {signedApprovers.map(a => (
                                  <option key={a.userId} value={a.userId}>{a.fullName}</option>
                                ))}
                              </select>
                            )}
                          </span>
                        </label>
                      )}
                      {(levelOptions?.allowReturnToDrafter !== false) && (
                        <label className="flex items-start gap-2 rounded border border-amber-200 bg-white px-2 py-1.5 text-[12px] hover:bg-amber-50/40">
                          <input
                            type="radio"
                            className="mt-0.5"
                            checked={returnMode === WorkflowReturnMode.Drafter}
                            onChange={() => setReturnMode(WorkflowReturnMode.Drafter)}
                          />
                          <span>
                            <span className="font-medium">Trả về Người soạn thảo (mặc định)</span>
                            <span className="block text-[10px] text-slate-500">Phase → "Trả lại". Drafter sửa rồi gửi lại chạy từ Cấp 1 Bước 1.</span>
                          </span>
                        </label>
                      )}
                    </div>
                  </div>
                )}
                <div className="mb-3 rounded border border-amber-200 bg-amber-50 px-3 py-2 text-[11px] text-amber-800">
                  {returnMode === WorkflowReturnMode.Drafter
                    ? 'Phiếu sẽ về "Trả lại". Drafter có thể sửa rồi trình lại từ Cấp 1 Bước 1.'
                    : returnMode === WorkflowReturnMode.Assignee
                      ? 'Phiếu sẽ về Cấp/Bước của NV đã chọn (vẫn "Đã gửi duyệt"). NV nhận lại để duyệt tiếp.'
                      : 'Phiếu sẽ lùi pointer (vẫn "Đã gửi duyệt"). NV trước nhận lại để duyệt tiếp.'}
                </div>
              </>
            )}
            <Label>Ghi chú (tùy chọn)</Label>
            <Textarea value={comment} onChange={e => setComment(e.target.value)} rows={3} />
          </Dialog>
        )
      })()}

      {deptApprovals.length > 0 && (
        <div className="border-t border-slate-200 pt-4">
          <DeptApprovalsSection rows={deptApprovals} currentPhase={evaluation.phase} />
        </div>
      )}

      <div className="border-t border-slate-200 pt-4">
        <PeApprovalsSection ev={evaluation} />
      </div>

      <div className="border-t border-slate-200 pt-4">
        <PeHistorySection ev={evaluation} />
      </div>
    </div>
  )
}

// 2-stage dept approval timeline (Migration 16). Group by phase × dept,
// show Review NV row + Confirm TPB row. Highlight pending khi current phase
// có Review nhưng chưa Confirm → user biết "đang chờ TPB confirm".
function DeptApprovalsSection({
  rows,
  currentPhase,
}: {
  rows: PeDepartmentApproval[]
  currentPhase: number
}) {
  // Group: phase → dept → stages
  const grouped = new Map<number, Map<string, PeDepartmentApproval[]>>()
  for (const r of rows) {
    if (!grouped.has(r.phaseAtApproval)) grouped.set(r.phaseAtApproval, new Map())
    const byDept = grouped.get(r.phaseAtApproval)!
    if (!byDept.has(r.departmentId)) byDept.set(r.departmentId, [])
    byDept.get(r.departmentId)!.push(r)
  }
  // Order: phase asc
  const phaseOrder = [...grouped.keys()].sort((a, b) => a - b)

  return (
    <div>
      <h3 className="text-sm font-semibold text-slate-900">Tiến trình duyệt 2-cấp phòng ban</h3>
      <p className="mt-0.5 text-[11px] text-slate-500">NV Review → TPB Confirm. Phase chỉ chuyển khi có Confirm.</p>
      <div className="mt-2 space-y-3">
        {phaseOrder.map(phase => {
          const byDept = grouped.get(phase)!
          return (
            <div key={phase}>
              <div className={cn(
                'inline-block rounded px-1.5 py-0.5 text-[10px] font-medium',
                PurchaseEvaluationPhaseColor[phase],
              )}>
                {PurchaseEvaluationPhaseLabel[phase]}
              </div>
              <div className="mt-1 space-y-1.5">
                {[...byDept.entries()].map(([deptId, stages]) => {
                  const review = stages.find(s => s.stage === ApprovalStage.Review)
                  const confirm = stages.find(s => s.stage === ApprovalStage.Confirm)
                  const deptName = stages[0]?.departmentName ?? '(không rõ phòng)'
                  const isPending = phase === currentPhase && review && !confirm
                  return (
                    <div key={deptId} className={cn(
                      'rounded border px-2 py-1.5 text-[11px]',
                      isPending ? 'border-amber-300 bg-amber-50' : 'border-slate-200 bg-slate-50',
                    )}>
                      <div className="font-medium text-slate-700">{deptName}</div>
                      <div className="mt-1 grid grid-cols-[60px_1fr] gap-x-2 gap-y-0.5">
                        <span className="text-slate-500">Review:</span>
                        <span className={review ? 'text-slate-700' : 'text-slate-400'}>
                          {review
                            ? <>✓ {review.approverName} <span className="text-slate-500">— {fmtTime(review.approvedAt)}</span>{review.comment && <span className="text-slate-500"> · "{review.comment}"</span>}</>
                            : '— chưa có'}
                        </span>
                        <span className="text-slate-500">Confirm:</span>
                        <span className={confirm ? 'text-emerald-700' : 'text-amber-700'}>
                          {confirm
                            ? <>✓ {confirm.approverName}{confirm.isBypassed && <span className="ml-1 rounded bg-fuchsia-100 px-1 text-[9px] text-fuchsia-700">bypass</span>} <span className="text-slate-500">— {fmtTime(confirm.approvedAt)}</span>{confirm.comment && <span className="text-slate-500"> · "{confirm.comment}"</span>}</>
                            : '⏳ chờ TPB confirm'}
                        </span>
                      </div>
                    </div>
                  )
                })}
              </div>
            </div>
          )
        })}
      </div>
    </div>
  )
}

function fmtTime(iso: string): string {
  const d = new Date(iso)
  return d.toLocaleString('vi-VN', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' })
}

