'use client';

import { useEffect, useMemo, useState } from 'react';
import Link from 'next/link';
import { ChevronDown, ChevronRight, FileText, Plus } from 'lucide-react';

import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { cn } from '@/lib/utils';
import { StatusPill, type StatusPillStatus } from '@/components/ui/status-pill';
import { EmptyState } from '@/components/ui/empty-state';
import { PageHeader } from '@/components/shared/page-header';
import { PermissionGate } from '@/components/shared/permission-gate';
import { usePaginatedQuery } from '@/hooks/use-paginated-query';
import { useRealtimeInvalidation } from '@/hooks/use-realtime-invalidation';
import { useDocumentFolders, type FolderNode } from '@/hooks/use-document-folders';
import { useMobileChrome } from '@/components/layout/mobile/mobile-layout-provider';
import { FolderActionsMenu } from './folder-actions-menu';
import { FolderBreadcrumb } from './folder-breadcrumb';
import { FolderTreeSidebar } from './folder-tree-sidebar';
import { HubRootView } from './hub-root-view';
import { EntityFolderView } from './entity-folder-view';

interface HubDoc {
  id: string;
  documentType: string;
  title: string;
  status: string;
  createdAt: string;
  signers?: Array<{ id: string; signerEmail: string; signerName: string; status: string }>;
}

const TYPE_LABELS: Record<string, string> = {
  eoi: 'EOI',
  contract: 'Contract',
  nda: 'NDA',
  reservation_agreement: 'Reservation Agreement',
  welcome_letter: 'Welcome Letter',
  handover_checklist: 'Handover',
  acknowledgment: 'Acknowledgment',
  correspondence: 'Correspondence',
  other: 'Other',
};

const STATUS_PILL_MAP: Record<string, StatusPillStatus> = {
  draft: 'draft',
  sent: 'sent',
  partially_signed: 'partial',
  completed: 'completed',
  signed: 'signed',
  expired: 'expired',
  cancelled: 'cancelled',
  rejected: 'rejected',
};

const SIGNER_STATUS_LABELS: Record<string, string> = {
  pending: 'Pending',
  sent: 'Sent',
  signed: 'Signed',
  declined: 'Declined',
  expired: 'Expired',
  cancelled: 'Cancelled',
};

// Runtime guard so we don't cast `entityType` from the FolderNode shape; if a
// future system folder shape leaks an unexpected entity type the UI falls
// back to FlatFolderListing instead of crashing on a bad route.
const ENTITY_TYPES = new Set(['client', 'company', 'yacht'] as const);
type EntityType = 'client' | 'company' | 'yacht';
function isEntityType(v: unknown): v is EntityType {
  return typeof v === 'string' && ENTITY_TYPES.has(v as EntityType);
}

interface DocumentsHubProps {
  portSlug: string;
}

function findInTree(nodes: FolderNode[], id: string): FolderNode | null {
  for (const n of nodes) {
    if (n.id === id) return n;
    const found = findInTree(n.children, id);
    if (found) return found;
  }
  return null;
}

export function DocumentsHub({ portSlug }: DocumentsHubProps) {
  // undefined = "All documents" (no folder selected / hub root)
  // null = root folder only
  // string = specific folder id
  const [selectedFolderId, setSelectedFolderId] = useState<string | null | undefined>(undefined);

  const { data: tree = [] } = useDocumentFolders();

  // Realtime invalidation covers ALL three render modes (HubRootView,
  // EntityFolderView, FlatFolderListing) so navigating between modes
  // doesn't tear down the subscription. The hook-level eventKeysSig
  // dedup means the inline literal is safe across re-renders.
  useRealtimeInvalidation({
    'document:created': [['documents']],
    'document:updated': [['documents']],
    'document:deleted': [['documents']],
    'document:sent': [['documents']],
    'document:completed': [['documents'], ['files']],
    'document:expired': [['documents']],
    'document:cancelled': [['documents']],
    'document:rejected': [['documents']],
    'document:signer:signed': [['documents']],
    'file:created': [['files']],
    'file:updated': [['files']],
    'file:deleted': [['files']],
    'folder:created': [['document-folders']],
    'folder:updated': [['document-folders']],
    'folder:deleted': [['document-folders']],
    'folder:moved': [['document-folders']],
  });

  const { setChrome } = useMobileChrome();
  useEffect(() => {
    setChrome({ title: 'Documents' });
    return () => setChrome({ title: null });
  }, [setChrome]);

  const selectedFolder =
    typeof selectedFolderId === 'string' ? findInTree(tree, selectedFolderId) : null;

  const folderEntityType = selectedFolder?.entityType;
  const isEntityFolder =
    selectedFolder?.systemManaged === true &&
    folderEntityType != null &&
    folderEntityType !== 'root' &&
    selectedFolder.entityId != null &&
    isEntityType(folderEntityType);

  const handleFolderSelect = (id: string | null | undefined) => {
    setSelectedFolderId(id);
  };

  return (
    <div className="flex flex-col sm:flex-row h-full">
      <FolderTreeSidebar
        selectedFolderId={selectedFolderId}
        onSelect={handleFolderSelect}
        footer={
          <PermissionGate resource="documents" action="manage_folders">
            <FolderActionsMenu
              selectedFolderId={selectedFolderId}
              onAfterDelete={() => handleFolderSelect(undefined)}
            />
          </PermissionGate>
        }
      />
      <div className="flex-1 min-w-0 p-4 space-y-4">
        <div className="flex items-center justify-between gap-3">
          <FolderBreadcrumb selectedFolderId={selectedFolderId} onSelect={handleFolderSelect} />
          {selectedFolderId !== undefined && (
            <Button asChild size="sm">
              <Link href={`/${portSlug}/documents/new`}>
                <Plus className="mr-1.5 h-4 w-4" />
                New document
              </Link>
            </Button>
          )}
        </div>

        {selectedFolderId === undefined ? (
          <>
            <PageHeader
              title="Documents"
              description="Track signing status, chase pending signers, and audit completion."
              actions={
                <Button asChild>
                  <Link href={`/${portSlug}/documents/new`}>
                    <Plus className="mr-1.5 h-4 w-4" />
                    New document
                  </Link>
                </Button>
              }
              variant="gradient"
            />
            <HubRootView portSlug={portSlug} />
          </>
        ) : isEntityFolder && isEntityType(folderEntityType) ? (
          <EntityFolderView
            portSlug={portSlug}
            entityType={folderEntityType}
            entityId={selectedFolder!.entityId!}
          />
        ) : (
          <FlatFolderListing
            key={selectedFolderId ?? 'root'}
            portSlug={portSlug}
            folderId={selectedFolderId}
          />
        )}
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// FlatFolderListing — the original search + type-chip + document rows panel,
// now scoped to a specific folder (or null for root-only).
// ---------------------------------------------------------------------------

interface FlatFolderListingProps {
  portSlug: string;
  folderId: string | null;
}

function FlatFolderListing({ portSlug, folderId }: FlatFolderListingProps) {
  const [search, setSearch] = useState('');
  const [typeFilter, setTypeFilter] = useState<string | undefined>(undefined);
  const [expandedDocId, setExpandedDocId] = useState<string | null>(null);

  const queryParams = useMemo(() => {
    const params = new URLSearchParams();
    if (search) params.set('search', search);
    if (typeFilter) params.set('documentType', typeFilter);
    // folderId null = root, string = specific folder
    params.set('folderId', folderId ?? '');
    return params;
  }, [search, typeFilter, folderId]);

  const { data: documents, isLoading } = usePaginatedQuery<HubDoc>({
    queryKey: ['documents', 'hub', 'folder', queryParams.toString()],
    endpoint: `/api/v1/documents?${queryParams.toString()}`,
    filterDefinitions: [],
  });

  // Realtime invalidation is lifted to DocumentsHub so it survives mode
  // switches (root / entity-folder / flat-folder). Don't re-subscribe here.

  const renderRow = (doc: HubDoc) => {
    const expanded = expandedDocId === doc.id;
    const totalSigners = doc.signers?.length ?? 0;
    const signedCount = doc.signers?.filter((s) => s.status === 'signed').length ?? 0;
    const pillStatus = STATUS_PILL_MAP[doc.status] ?? 'pending';

    const isNonSignature = [
      'welcome_letter',
      'handover_checklist',
      'acknowledgment',
      'correspondence',
    ].includes(doc.documentType);

    return (
      <li
        key={doc.id}
        className="border-b last:border-b-0 transition-colors hover:bg-gradient-brand-soft/40"
      >
        <div className="flex flex-wrap items-center gap-x-3 gap-y-1 px-4 py-3 text-sm sm:grid sm:grid-cols-[auto_1fr_auto_auto_auto_auto] sm:gap-3">
          <button
            type="button"
            aria-label={`${expanded ? 'Collapse' : 'Expand'} signers for ${doc.title}`}
            aria-expanded={expanded}
            onClick={() => setExpandedDocId(expanded ? null : doc.id)}
            className="flex min-h-[44px] min-w-[44px] items-center justify-center text-muted-foreground transition-transform"
          >
            {expanded ? <ChevronDown className="h-4 w-4" /> : <ChevronRight className="h-4 w-4" />}
          </button>
          <Link
            href={`/${portSlug}/documents/${doc.id}`}
            className="min-w-0 truncate font-medium text-foreground hover:text-brand"
          >
            {doc.title}
          </Link>
          <span className="text-xs text-muted-foreground">
            {TYPE_LABELS[doc.documentType] ?? doc.documentType}
          </span>
          <StatusPill
            status={isNonSignature && doc.status === 'sent' ? 'delivered' : pillStatus}
            withDot
          >
            {isNonSignature && doc.status === 'sent' ? 'Delivered' : doc.status.replace(/_/g, ' ')}
          </StatusPill>
          <span className="text-xs tabular-nums text-muted-foreground">
            {totalSigners > 0 ? `${signedCount}/${totalSigners} signed` : '-'}
          </span>
          <span className="text-xs text-muted-foreground">
            {new Date(doc.createdAt).toLocaleDateString('en-GB')}
          </span>
        </div>
        {expanded && doc.signers && doc.signers.length > 0 ? (
          <div className="border-t bg-muted/30 px-12 py-2">
            <ul className="space-y-1">
              {doc.signers.map((signer) => (
                <li key={signer.id} className="flex items-center justify-between gap-2 text-xs">
                  <div className="flex min-w-0 items-center gap-2">
                    <span className="font-medium text-foreground">{signer.signerName}</span>
                    <span className="truncate text-muted-foreground">{signer.signerEmail}</span>
                  </div>
                  <StatusPill status={STATUS_PILL_MAP[signer.status] ?? 'pending'}>
                    {SIGNER_STATUS_LABELS[signer.status] ?? signer.status}
                  </StatusPill>
                </li>
              ))}
            </ul>
          </div>
        ) : null}
      </li>
    );
  };

  return (
    <>
      <div className="flex flex-wrap items-center gap-2">
        <Input
          placeholder="Search by title..."
          aria-label="Search documents by title"
          value={search}
          onChange={(e) => setSearch(e.target.value)}
          className="max-w-xs h-9"
        />
        {(() => {
          const seenTypes = Array.from(new Set(documents.map((d) => d.documentType))).sort();
          if (seenTypes.length === 0) return null;
          return (
            <div className="flex flex-wrap gap-1.5">
              <button
                type="button"
                aria-pressed={typeFilter === undefined}
                className={cn(
                  'inline-flex min-h-[44px] items-center rounded-full border px-3 py-2 text-xs',
                  typeFilter === undefined ? 'bg-foreground text-background' : 'hover:bg-accent',
                )}
                onClick={() => setTypeFilter(undefined)}
              >
                All types
              </button>
              {seenTypes.map((t) => (
                <button
                  type="button"
                  key={t}
                  aria-pressed={typeFilter === t}
                  className={cn(
                    'inline-flex min-h-[44px] items-center rounded-full border px-3 py-2 text-xs',
                    typeFilter === t ? 'bg-foreground text-background' : 'hover:bg-accent',
                  )}
                  onClick={() => setTypeFilter(t)}
                >
                  {TYPE_LABELS[t] ?? t}
                </button>
              ))}
            </div>
          );
        })()}
      </div>

      {isLoading ? (
        <ul className="rounded-md border bg-white">
          {[0, 1, 2, 3, 4].map((i) => (
            <li key={i} className="h-12 animate-pulse border-b last:border-b-0 bg-muted/40" />
          ))}
        </ul>
      ) : documents.length === 0 ? (
        <EmptyState
          icon={<FileText className="h-7 w-7" />}
          title="No documents in this folder"
          body="Create a document or move existing ones here."
          actions={
            <Button asChild>
              <Link href={`/${portSlug}/documents/new`}>
                <Plus className="mr-1.5 h-4 w-4" />
                New document
              </Link>
            </Button>
          }
        />
      ) : (
        <ul className="rounded-md border bg-white shadow-xs">{documents.map(renderRow)}</ul>
      )}
    </>
  );
}
