'use client';
import { Correspondence } from '@/types/correspondence';
import { StatusBadge } from '@/components/common/status-badge';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { format } from 'date-fns';
import { ArrowLeft, Download, FileText, Loader2, Send, CheckCircle, XCircle, Edit, Ban, AlertTriangle } from 'lucide-react';
import Link from 'next/link';
import { useSubmitCorrespondence, useProcessWorkflow, useCancelCorrespondence } from '@/hooks/use-correspondence';
import { ReferenceSelector } from '@/components/correspondences/reference-selector';
import { TagManager } from '@/components/correspondences/tag-manager';
import { CirculationStatusCard } from '@/components/correspondences/circulation-status-card';
import { RevisionHistory } from '@/components/correspondences/revision-history';
import { Can } from '@/components/common/can';
import { useAuthStore } from '@/lib/stores/auth-store';
import { useState } from 'react';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import { Input } from '@/components/ui/input';
import { Badge } from '@/components/ui/badge';
interface CorrespondenceDetailProps {
data: Correspondence;
selectedRevisionId?: string;
}
const normalizeUuid = (value?: string): string | undefined => {
if (typeof value !== 'string') {
return undefined;
}
const normalized = value.trim().toLowerCase();
return normalized.length > 0 ? normalized : undefined;
};
export function CorrespondenceDetail({ data, selectedRevisionId }: CorrespondenceDetailProps) {
const submitMutation = useSubmitCorrespondence();
const processMutation = useProcessWorkflow();
const cancelMutation = useCancelCorrespondence();
const { user, hasPermission } = useAuthStore();
const [actionState, setActionState] = useState<'approve' | 'reject' | 'cancel' | null>(null);
const [comments, setComments] = useState('');
const [cancelReason, setCancelReason] = useState('');
if (!data) return
No data found
;
const normalizedSelectedRevisionId = normalizeUuid(selectedRevisionId);
const selectedRevision = normalizedSelectedRevisionId
? data.revisions?.find((r) => normalizeUuid(r.publicId) === normalizedSelectedRevisionId)
: undefined;
const currentRevision = selectedRevision || data.revisions?.find((r) => r.isCurrent) || data.revisions?.[0];
const subject = currentRevision?.subject || '-';
const description = currentRevision?.description || '-';
const status = currentRevision?.status?.statusCode || 'UNKNOWN';
const attachments = currentRevision?.attachments || [];
const importance = (currentRevision?.details?.importance as string) || 'NORMAL';
const canEditMetadata = hasPermission('correspondence.edit');
const privilegedEditableStatuses = ['SUBCSC', 'SUBOWN', 'IN_REVIEW_CSC'];
const normalizedRole = (user?.role || '').toUpperCase().replace(/\s+/g, '_');
const isPrivilegedEditRole = ['SUPERADMIN', 'SUPER_ADMIN', 'ADMIN', 'DC', 'DOCUMENT_CONTROL'].includes(
normalizedRole
);
const canEditInStatus =
status === 'DRAFT' ||
(privilegedEditableStatuses.includes(status) && isPrivilegedEditRole);
const canEditDocument = canEditInStatus && (hasPermission('correspondence.edit') || isPrivilegedEditRole);
const toRecipients = data.recipients?.filter((r) => r.recipientType === 'TO') || [];
const ccRecipients = data.recipients?.filter((r) => r.recipientType === 'CC') || [];
const handleSubmit = () => {
if (confirm('Are you sure you want to submit this correspondence?')) {
submitMutation.mutate({ uuid: data.publicId, data: {} });
}
};
const handleProcess = () => {
if (!actionState || actionState === 'cancel') return;
const action = actionState === 'approve' ? 'APPROVE' : 'REJECT';
processMutation.mutate(
{ uuid: data.publicId, data: { action, comments } },
{ onSuccess: () => { setActionState(null); setComments(''); } }
);
};
const handleCancel = () => {
if (!cancelReason.trim()) return;
cancelMutation.mutate(
{ uuid: data.publicId, reason: cancelReason },
{ onSuccess: () => { setActionState(null); setCancelReason(''); } }
);
};
return (
{/* EC-CORR-002 Warning: Replying to cancelled document */}
{status === 'CANCELLED' && (
This correspondence has been cancelled
You can still create a new correspondence referencing this document to acknowledge the cancellation.
)}
{/* Header / Actions */}
{data.correspondenceNumber}
Created on {data.createdAt ? format(new Date(data.createdAt), 'dd MMM yyyy HH:mm') : '-'}
{canEditDocument && (
)}
{status === 'DRAFT' && (
)}
{status === 'IN_REVIEW' && (
<>
>
)}
{status !== 'CANCELLED' && (
)}
{/* Approve / Reject Input Area */}
{(actionState === 'approve' || actionState === 'reject') && (
{actionState === 'approve' ? 'Confirm Approval' : 'Confirm Rejection'}
)}
{/* Cancel Confirmation (EC-CORR-001) */}
{actionState === 'cancel' && (
Cancel Correspondence
Cancelling will permanently change this document's status and force-close any active circulations
linked to it. This action cannot be undone.
setCancelReason(e.target.value)}
placeholder="Enter reason for cancellation..."
/>
)}
{/* Main Content */}
{subject}
{description && description !== '-' && (
Description
{description}
)}
{currentRevision?.body && (
Content
{currentRevision.body}
)}
{currentRevision?.remarks && (
Remarks
{currentRevision.remarks}
)}
Attachments
{attachments.length > 0 ? (
{attachments.map((file, index) => (
))}
) : (
No attachments found.
)}
{/* Sidebar */}
{/* Core Info */}
Information
Importance
{String(importance)}
Document Type
{data.type?.typeName || '-'} ({data.type?.typeCode || '-'})
Originator (From)
{data.originator?.organizationName || '-'}
{data.originator?.organizationCode}
To
{toRecipients.length > 0 ? (
{toRecipients.map((r) => (
{r.recipientOrganization?.organizationName || '-'}
{r.recipientOrganization?.organizationCode}
))}
) : (
-
)}
{ccRecipients.length > 0 && (
CC
{ccRecipients.map((r) => (
{r.recipientOrganization?.organizationCode || '-'}
))}
)}
Project
{data.project?.projectName || '-'}
{data.project?.projectCode}
{/* Dates */}
Dates
{(
[
{ label: 'Document Date', value: currentRevision?.documentDate },
{ label: 'Issued Date', value: currentRevision?.issuedDate },
{ label: 'Received Date', value: currentRevision?.receivedDate },
{ label: 'Due Date', value: currentRevision?.dueDate },
] as { label: string; value?: string }[]
).map(({ label, value }) => (
{label}
{value ? format(new Date(value), 'dd MMM yyyy') : '-'}
))}
{/* Circulations */}
{/* Tags */}
{/* References */}
{/* Revision History */}
{data.revisions && data.revisions.length > 0 && (
)}
);
}