import { A, useParams, useSearchParams } from '@solidjs/router';
import { createMemo, createResource, createSignal, For, Show, createEffect } from 'solid-js';

const API = '';

// Documents submitted for verification are stored as permanent Backblaze URLs.
// Never render one of those directly (img src / a href) — always exchange it for
// a short-lived signed URL through this endpoint first, on demand.
async function presignDocUrl(url: string): Promise<string> {
  try {
    const res = await fetch(`${API}/api/admin/verifications/presign`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ url }),
    });
    if (!res.ok) return url;
    const data = await res.json();
    return data?.url ?? url;
  } catch {
    return url;
  }
}

// ── Types ──────────────────────────────────────────────────────────

type RoleType =
  | 'COMPANY' | 'CANDIDATE' | 'CUSTOMER' | 'PHOTOGRAPHER' | 'MAKEUP_ARTIST'
  | 'TUTOR' | 'DEVELOPER' | 'VIDEO_EDITOR' | 'GRAPHIC_DESIGNER'
  | 'SOCIAL_MEDIA_MANAGER' | 'FITNESS_TRAINER' | 'CATERING_SERVICE'
  | 'ADMIN' | 'UNKNOWN';

interface SubmissionData {
  user: {
    id: string;
    name?: string;
    email: string;
    phone?: string;
    status: string;
    email_verified: boolean;
    created_at: string;
  };
  role_key?: string;
  submission?: {
    id?: string;
    status: string;
    payload: Record<string, unknown>;
    completed_at?: string;
    updated_at: string;
  } | null;
}

interface AdminRemark {
  type: 'INFO' | 'CHANGES_REQUESTED' | 'MORE_DOCUMENTS_REQUESTED' | 'REJECTED';
  comment: string;
  fields?: string[];
}

// ── Helpers ──────────────────────────────────────────────────────────

function inferRoleType(roleKey?: string, name?: string): RoleType {
  const raw = [roleKey, name].filter(Boolean).join(' ').toLowerCase();
  if (raw.includes('photographer')) return 'PHOTOGRAPHER';
  if (raw.includes('makeup')) return 'MAKEUP_ARTIST';
  if (raw.includes('tutor')) return 'TUTOR';
  if (raw.includes('developer')) return 'DEVELOPER';
  if (raw.includes('video') || raw.includes('video_editor')) return 'VIDEO_EDITOR';
  if (raw.includes('graphic') || raw.includes('graphic_designer')) return 'GRAPHIC_DESIGNER';
  if (raw.includes('social') || raw.includes('social_media')) return 'SOCIAL_MEDIA_MANAGER';
  if (raw.includes('fitness') || raw.includes('fitness_trainer')) return 'FITNESS_TRAINER';
  if (raw.includes('catering')) return 'CATERING_SERVICE';
  if (raw.includes('customer')) return 'CUSTOMER';
  if (raw.includes('job_seeker') || raw.includes('candidate')) return 'CANDIDATE';
  if (raw.includes('company')) return 'COMPANY';
  if (raw.includes('admin') || raw.includes('employee')) return 'ADMIN';
  return 'UNKNOWN';
}

function managementDest(roleType: RoleType): { label: string; href: string } {
  const map: Record<RoleType, { label: string; href: string }> = {
    COMPANY: { label: 'Company Management', href: '/admin/company' },
    CANDIDATE: { label: 'Candidate Management', href: '/admin/candidate' },
    CUSTOMER: { label: 'Customer Management', href: '/admin/customer' },
    PHOTOGRAPHER: { label: 'Photographer Management', href: '/admin/photographer' },
    MAKEUP_ARTIST: { label: 'Makeup Artist Management', href: '/admin/makeup-artist' },
    TUTOR: { label: 'Tutors Management', href: '/admin/tutors' },
    DEVELOPER: { label: 'Developers Management', href: '/admin/developers' },
    VIDEO_EDITOR: { label: 'Video Editor Management', href: '/admin/video-editors' },
    GRAPHIC_DESIGNER: { label: 'Graphics Designer Management', href: '/admin/graphic-designers' },
    SOCIAL_MEDIA_MANAGER: { label: 'Social Media Manager Management', href: '/admin/social-media-managers' },
    FITNESS_TRAINER: { label: 'Fitness Trainer Management', href: '/admin/fitness-trainers' },
    CATERING_SERVICE: { label: 'Catering Services Management', href: '/admin/catering-services' },
    ADMIN: { label: 'Employee Management', href: '/admin/employees' },
    UNKNOWN: { label: 'Users Management', href: '/admin/users' },
  };
  return map[roleType] ?? map.UNKNOWN;
}

/** Flatten nested JSON into key→value pairs for display */
function flattenFields(obj: Record<string, unknown>, prefix = ''): Array<{ key: string; value: string }> {
  const result: Array<{ key: string; value: string }> = [];
  for (const [k, v] of Object.entries(obj)) {
    const label = prefix ? `${prefix}.${k}` : k;
    if (v !== null && typeof v === 'object' && !Array.isArray(v)) {
      result.push(...flattenFields(v as Record<string, unknown>, label));
    } else if (Array.isArray(v)) {
      result.push({ key: label, value: v.join(', ') });
    } else {
      result.push({ key: label, value: String(v ?? '—') });
    }
  }
  return result;
}

/** Skip internal tracking fields — only show what the user actually submitted */
const SKIP_KEYS = new Set(['step', 'total', 'currentStep', '__version', '__schema']);

function isSubmittedField(key: string): boolean {
  return !SKIP_KEYS.has(key) && !key.startsWith('_');
}

const ROLE_COLORS: Record<RoleType, string> = {
  COMPANY: 'background:#dbeafe;color:#1d4ed8',
  CANDIDATE: 'background:#e0e7ff;color:#4338ca',
  CUSTOMER: 'background:#cffafe;color:#0e7490',
  PHOTOGRAPHER: 'background:#ede9fe;color:#6d28d9',
  MAKEUP_ARTIST: 'background:#fce7f3;color:#9d174d',
  TUTOR: 'background:#d1fae5;color:#065f46',
  DEVELOPER: 'background:#e0f2fe;color:#0369a1',
  VIDEO_EDITOR: 'background:#fef3c7;color:#92400e',
  GRAPHIC_DESIGNER: 'background:#f0fdf4;color:#166534',
  SOCIAL_MEDIA_MANAGER: 'background:#fdf2f8;color:#86198f',
  FITNESS_TRAINER: 'background:#fff7ed;color:#9a3412',
  CATERING_SERVICE: 'background:#fefce8;color:#854d0e',
  ADMIN: 'background:#f1f5f9;color:#334155',
  UNKNOWN: 'background:#f8fafc;color:#64748b',
};

// ── Field type detection ──────────────────────────────────────────────────────────

type FieldKind = 'image' | 'pdf' | 'document' | 'url' | 'text';

function detectKind(key: string, value: string): FieldKind {
  const k = key.toLowerCase();
  const v = (value || '').toLowerCase();

  // Image: key hints OR common image extensions
  if (
    /photo|image|picture|avatar|selfie|headshot|thumbnail|profile_pic/i.test(k) ||
    /\.(jpg|jpeg|png|gif|webp|bmp|svg)(\?|$)/i.test(v)
  ) return 'image';

  // PDF
  if (/\.(pdf)(\?|$)/i.test(v) || /pdf|resume|cv\b/i.test(k)) return 'pdf';

  // Generic document/upload (not image/pdf)
  if (
    /upload|document|file|attachment|certificate|license|govt_id|aadhaar|pan|passport|degree|transcript|portfolio|id_proof/i.test(k) ||
    /\.(doc|docx|xls|xlsx|ppt|pptx|zip|rar)(\?|$)/i.test(v)
  ) return 'document';

  // URL that isn't a file
  if (value.startsWith('http') || value.startsWith('/')) return 'url';

  return 'text';
}

// ── Data loaders ──────────────────────────────────────────────────────────

async function loadSubmission(args: { subjectId: string; roleKey: string }): Promise<SubmissionData | null> {
  if (!args.subjectId) return null;
  try {
    const qs = args.roleKey ? `?roleKey=${encodeURIComponent(args.roleKey)}` : '';
    const res = await fetch(`${API}/api/admin/approvals/submission/${args.subjectId}${qs}`);
    if (!res.ok) return null;
    const raw = await res.json();
    return raw;
  } catch {
    return null;
  }
}

// ── Page ──────────────────────────────────────────────────────────

export default function ApprovalDetailPage() {
  const params = useParams();
  const [searchParams] = useSearchParams();

  // params.id is a legacy subject id. If submission payload includes verification id,
  // that id is used for final profile approval actions.
  const subjectId = () => params.id;
  const roleKey = () => (searchParams.roleKey as string) || '';

  const [data] = createResource(
    () => ({ subjectId: subjectId(), roleKey: roleKey() }),
    loadSubmission,
  );

  const [acting, setActing] = createSignal('');
  const [actionError, setActionError] = createSignal('');
  const [actionDone, setActionDone] = createSignal('');

  const roleType = createMemo(() => inferRoleType(data()?.role_key, undefined));
  const dest = createMemo(() => managementDest(roleType()));
  const submissionData = createMemo(() => {
    const current = data();
    if (!current) return null;
    if (current.submission) {
      return {
        status: current.submission.status,
        progress_json: current.submission.payload || {},
        completed_at: current.submission.completed_at,
        updated_at: current.submission.updated_at,
      };
    }
    return null;
  });

  // Flatten progress_json into displayable rows
  const submittedRows = createMemo(() => {
    const pj = submissionData()?.progress_json;
    if (!pj || typeof pj !== 'object') return [];
    return flattenFields(pj as Record<string, unknown>)
      .filter((f) => isSubmittedField(f.key));
  });

  // ── Approve / Reject  ──
  // Routes: POST /api/admin/approvals/profiles/{verification_id}/approve|reject

  const getApprovalPath = (action: 'approve' | 'reject') => {
    const id = data()?.submission?.id || subjectId();
    if (!id) return null;
    return `/api/admin/approvals/profiles/${id}/${action}`;
  };

  const handleApprove = async () => {
    if (!confirm('Approve this profile submission?')) return;
    const path = getApprovalPath('approve');
    if (!path) { setActionError('Cannot resolve approval endpoint — roleKey missing in URL'); return; }
    try {
      setActing('APPROVE');
      setActionError('');
      const res = await fetch(`${API}${path}`, { method: 'POST' });
      if (!res.ok) throw new Error('Failed to approve');
      setActionDone('APPROVED');
    } catch (err: any) {
      setActionError(err.message || 'Failed to approve');
    } finally {
      setActing('');
    }
  };

  const handleReject = async () => {
    const reason = prompt('Rejection reason (required):');
    if (!reason?.trim()) return;
    const path = getApprovalPath('reject');
    if (!path) { setActionError('Cannot resolve rejection endpoint — roleKey missing in URL'); return; }
    try {
      setActing('REJECT');
      setActionError('');
      const res = await fetch(`${API}${path}`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ reason: reason.trim() }),
      });
      if (!res.ok) throw new Error('Failed to reject');
      setActionDone('REJECTED');
    } catch (err: any) {
      setActionError(err.message || 'Failed to reject');
    } finally {
      setActing('');
    }
  };

  return (
      <div class="flex flex-col -mx-6 -mt-6 min-h-full">
      <div class="bg-white border-b border-gray-200 px-6 py-4 flex items-center justify-between">
        <div>
          <h1 class="text-xl font-semibold text-gray-900">Submission Review</h1>
          <p class="text-sm text-gray-500 mt-0.5">Review verified submission data and apply final approval actions.</p>
        </div>
        <A class="rounded-lg border border-gray-200 px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 transition-colors" href="/admin/approval">← Back to Approvals</A>
      </div>
      <div class="p-6 flex-1">

      <Show when={actionError()}>
        <div class="mb-4 rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700" style="margin-bottom:12px">{actionError()}</div>
      </Show>

      <Show when={actionDone()}>
        <div class="rounded-xl border border-gray-200 bg-white shadow-sm" style="margin-bottom:12px;border-left:4px solid #22c55e;padding:12px 16px">
          <p style="margin:0;font-weight:600;color:#166534">
            {actionDone() === 'APPROVED' ? '✓ Profile approved successfully.' : '✕ Profile rejected.'}
          </p>
          <A href={dest().href} style="font-size:13px;color:#15803d;text-decoration:underline">
            Open {dest().label} →
          </A>
        </div>
      </Show>

      <Show when={data.loading}>
        <div class="rounded-xl border border-gray-200 bg-white shadow-sm"><p class="notice">Loading submission...</p></div>
      </Show>

      <Show when={!data.loading && !data()}>
        <div class="rounded-xl border border-gray-200 bg-white shadow-sm">
          <p class="notice">Submission not found or no verification packet is available for this role.</p>
          <p style="font-size:13px;color:#64748b;margin-top:8px">
            Make sure the URL includes <code>?roleKey=PHOTOGRAPHER</code> (or the relevant role key).
          </p>
        </div>
      </Show>

      <Show when={data()}>
        {/* ── Action bar ── */}
        <Show when={!actionDone()}>
          <div class="rounded-xl border border-gray-200 bg-white shadow-sm" style="display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:16px;padding:12px 16px">
            <span style={`display:inline-block;padding:3px 10px;border-radius:999px;font-size:12px;font-weight:600;${ROLE_COLORS[roleType()]}`}>
              {(roleKey() || 'UNKNOWN').replace(/_/g, ' ')}
            </span>
            <span style="font-size:13px;color:#64748b">
              Verification: <strong style={`color:${submissionData()?.status === 'APPROVED' ? '#15803d' : '#c2410c'}`}>
                {submissionData()?.status ?? 'NO DATA'}
              </strong>
            </span>
            <div style="flex:1" />
            <Show when={submissionData()?.status === 'APPROVED' && !actionDone()}>
              <button
                class="inline-flex items-center rounded-lg border border-gray-200 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 transition-colors"
                style="background:#f0fdf4;color:#15803d;border-color:#bbf7d0"
                disabled={!!acting()}
                onClick={handleApprove}
              >
                {acting() === 'APPROVE' ? 'Approving...' : '✓ Final Approve'}
              </button>
              <button
                class="inline-flex items-center rounded-lg border border-red-200 bg-red-50 px-4 py-2 text-sm font-medium text-red-600 hover:bg-red-100 transition-colors"
                disabled={!!acting()}
                onClick={handleReject}
              >
                {acting() === 'REJECT' ? 'Rejecting...' : '✕ Final Reject'}
              </button>
            </Show>
          </div>
        </Show>

        <div style="display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px">
          {/* User info */}
          <div class="rounded-xl border border-gray-200 bg-white shadow-sm">
            <h3 style="margin:0 0 12px;font-size:15px;font-weight:600;color:#0f172a">User Info</h3>
            <table style="width:100%;border-collapse:collapse;font-size:13px">
              <tbody>
                <tr><td style="color:#64748b;padding:5px 10px 5px 0;white-space:nowrap;width:40%">Name</td><td style="font-weight:500">{data()!.user.name || '—'}</td></tr>
                <tr><td style="color:#64748b;padding:5px 10px 5px 0">Email</td><td style="color:#475569">{data()!.user.email}</td></tr>
                <tr><td style="color:#64748b;padding:5px 10px 5px 0">Phone</td><td style="color:#475569">{data()!.user.phone || '—'}</td></tr>
                <tr>
                  <td style="color:#64748b;padding:5px 10px 5px 0">Account Status</td>
                  <td>
                    <span class={`inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-medium text-gray-600${data()!.user.status === 'ACTIVE' ? ' active' : ''}`}>
                      {data()!.user.status}
                    </span>
                  </td>
                </tr>
                <tr>
                  <td style="color:#64748b;padding:5px 10px 5px 0">Email Verified</td>
                  <td style={`font-weight:500;color:${data()!.user.email_verified ? '#15803d' : '#b91c1c'}`}>
                    {data()!.user.email_verified ? '✓ Yes' : '✕ No'}
                  </td>
                </tr>
                <tr><td style="color:#64748b;padding:5px 10px 5px 0">Registered</td><td style="color:#475569">{new Date(data()!.user.created_at).toLocaleDateString()}</td></tr>
                <tr><td style="color:#64748b;padding:5px 10px 5px 0">User ID</td><td style="font-family:ui-monospace,monospace;font-size:11px;color:#94a3b8">{data()!.user.id}</td></tr>
              </tbody>
            </table>
          </div>

          {/* Submission status */}
          <div class="rounded-xl border border-gray-200 bg-white shadow-sm">
            <h3 style="margin:0 0 12px;font-size:15px;font-weight:600;color:#0f172a">Submission Info</h3>
            <Show when={submissionData()} fallback={
              <div style="background:#fef2f2;border:1px solid #fecaca;border-radius:8px;padding:14px">
                <p style="margin:0;color:#b91c1c;font-weight:500">No verification data found</p>
                <p style="margin:6px 0 0;font-size:13px;color:#7f1d1d">
                  This user has not submitted verification payload data for role: <strong>{roleKey() || 'unknown'}</strong>
                </p>
              </div>
            }>
              <table style="width:100%;border-collapse:collapse;font-size:13px">
                <tbody>
                  <tr><td style="color:#64748b;padding:5px 10px 5px 0;white-space:nowrap;width:40%">Role</td><td style="font-weight:500">{(roleKey() || '—').replace(/_/g, ' ')}</td></tr>
                  <tr>
                    <td style="color:#64748b;padding:5px 10px 5px 0">Status</td>
                    <td>
                      <span style={`display:inline-block;padding:2px 8px;border-radius:4px;font-size:12px;font-weight:600;${submissionData()!.status === 'APPROVED' ? 'background:#dcfce7;color:#166534' : 'background:#fef9c3;color:#713f12'}`}>
                        {submissionData()!.status}
                      </span>
                    </td>
                  </tr>
                  <tr><td style="color:#64748b;padding:5px 10px 5px 0">Submitted</td><td style="color:#475569">{submissionData()!.completed_at ? new Date(submissionData()!.completed_at!).toLocaleString() : '—'}</td></tr>
                  <tr><td style="color:#64748b;padding:5px 10px 5px 0">Last Updated</td><td style="color:#475569">{new Date(submissionData()!.updated_at).toLocaleString()}</td></tr>
                  <tr><td style="color:#64748b;padding:5px 10px 5px 0">Fields</td><td style="color:#475569">{submittedRows().length} fields submitted</td></tr>
                </tbody>
              </table>
            </Show>
          </div>
        </div>

        {/* ── Submitted form answers + media viewer ── */}
        <Show when={submittedRows().length > 0}>
          <SubmissionViewer rows={submittedRows()} />
        </Show>

        {/* ── No form data fallback ── */}
        <Show when={submissionData() && submittedRows().length === 0}>
          <div class="rounded-xl border border-gray-200 bg-white shadow-sm" style="margin-bottom:16px">
            <h3 style="margin:0 0 10px;font-size:15px;font-weight:600;color:#0f172a">Submitted Form Answers</h3>
            <p class="notice">Submission state is present but contains no displayable field data.</p>
          </div>
        </Show>
      </Show>
      </div>
      </div>
  );
}

// ────────────────────────────── SubmissionViewer ──────────────────────────────

function SubmissionViewer(props: { rows: Array<{ key: string; value: string }> }) {
  const [lightbox, setLightbox] = createSignal<{ src: string; label: string } | null>(null);
  const [pdfViewer, setPdfViewer] = createSignal<{ src: string; label: string } | null>(null);

  // Split rows into text fields vs media
  const textFields = createMemo(() =>
    props.rows.filter((r) => {
      const kind = detectKind(r.key, r.value);
      return kind === 'text' || kind === 'url';
    })
  );
  const mediaFields = createMemo(() =>
    props.rows.filter((r) => {
      const kind = detectKind(r.key, r.value);
      return kind === 'image' || kind === 'pdf' || kind === 'document';
    })
  );

  return (
    <>
      {/* ── Text / data fields ── */}
      <Show when={textFields().length > 0}>
        <div class="rounded-xl border border-gray-200 bg-white shadow-sm" style="margin-bottom:16px">
          <h3 style="margin:0 0 14px;font-size:15px;font-weight:600;color:#0f172a">
            Submitted Form Data
            <span style="margin-left:8px;font-size:12px;font-weight:400;color:#64748b">{textFields().length} fields</span>
          </h3>
          <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:8px">
            <For each={textFields()}>
              {(field) => {
                const kind = detectKind(field.key, field.value);
                return (
                  <div style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:10px 12px">
                    <div style="font-size:10px;color:#94a3b8;margin-bottom:4px;font-weight:700;letter-spacing:0.05em">
                      {field.key.replace(/_/g, ' ').replace(/\./g, ' › ').toUpperCase()}
                    </div>
                    <Show when={kind === 'url'} fallback={
                      <div style="font-size:13px;color:#0f172a;word-break:break-all;line-height:1.5">{field.value || '—'}</div>
                    }>
                      <a href={field.value} target="_blank" rel="noreferrer"
                         style="font-size:13px;color:#2563eb;word-break:break-all">
                        🔗 {field.value}
                      </a>
                    </Show>
                  </div>
                );
              }}
            </For>
          </div>
        </div>
      </Show>

      {/* ── Documents & Images ── */}
      <Show when={mediaFields().length > 0}>
        <div class="rounded-xl border border-gray-200 bg-white shadow-sm" style="margin-bottom:16px">
          <h3 style="margin:0 0 14px;font-size:15px;font-weight:600;color:#0f172a">
            Documents & Media
            <span style="margin-left:8px;font-size:12px;font-weight:400;color:#64748b">{mediaFields().length} file{mediaFields().length !== 1 ? 's' : ''}</span>
          </h3>
          <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px">
            <For each={mediaFields()}>
              {(field) => {
                const kind = detectKind(field.key, field.value);
                const label = field.key.replace(/_/g, ' ').replace(/\./g, ' › ');
                return (
                  <div style="border:1px solid #e2e8f0;border-radius:10px;overflow:hidden;background:#fff">
                    {/* Preview area */}
                    <Show when={kind === 'image'}>
                      <div
                        style="background:#f1f5f9;cursor:pointer;position:relative;height:140px;display:flex;align-items:center;justify-content:center;overflow:hidden"
                        onClick={async () => setLightbox({ src: await presignDocUrl(field.value), label })}
                      >
                        <div style="display:flex;width:100%;height:100%;align-items:center;justify-content:center;flex-direction:column;gap:4px;color:#94a3b8">
                          <span style="font-size:32px">🖼</span>
                          <span style="font-size:11px">Click to view</span>
                        </div>
                      </div>
                    </Show>

                    <Show when={kind === 'pdf'}>
                      <div
                        style="background:#fef2f2;cursor:pointer;height:140px;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:6px"
                        onClick={async () => setPdfViewer({ src: await presignDocUrl(field.value), label })}
                      >
                        <span style="font-size:40px">📄</span>
                        <span style="font-size:12px;color:#b91c1c;font-weight:600">PDF Document</span>
                        <span style="font-size:11px;color:#94a3b8">Click to view</span>
                      </div>
                    </Show>

                    <Show when={kind === 'document'}>
                      <div style="background:#eff6ff;height:140px;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:6px">
                        <span style="font-size:40px">📎</span>
                        <span style="font-size:12px;color:#1d4ed8;font-weight:600">Document</span>
                        <button
                          type="button"
                          onClick={async (e) => {
                            e.stopPropagation();
                            const signed = await presignDocUrl(field.value);
                            window.open(signed, '_blank', 'noopener,noreferrer');
                          }}
                          style="font-size:11px;color:#2563eb;background:none;border:none;padding:0;cursor:pointer;text-decoration:underline"
                        >
                          Download
                        </button>
                      </div>
                    </Show>

                    {/* Label + open link */}
                    <div style="padding:8px 10px;border-top:1px solid #e2e8f0">
                      <div style="font-size:11px;color:#0f172a;font-weight:600;margin-bottom:4px;text-transform:capitalize">
                        {label}
                      </div>
                      <div style="display:flex;gap:6px">
                        <Show when={kind === 'image'}>
                          <button
                            type="button"
                            style="font-size:11px;color:#2563eb;background:none;border:none;padding:0;cursor:pointer;text-decoration:underline"
                            onClick={async () => setLightbox({ src: await presignDocUrl(field.value), label })}
                          >
                            🔍 View Full
                          </button>
                        </Show>
                        <Show when={kind === 'pdf'}>
                          <button
                            type="button"
                            style="font-size:11px;color:#b91c1c;background:none;border:none;padding:0;cursor:pointer;text-decoration:underline"
                            onClick={async () => setPdfViewer({ src: await presignDocUrl(field.value), label })}
                          >
                            📄 Open PDF
                          </button>
                        </Show>
                        <button
                          type="button"
                          onClick={async () => {
                            const signed = await presignDocUrl(field.value);
                            window.open(signed, '_blank', 'noopener,noreferrer');
                          }}
                          style="font-size:11px;color:#64748b;background:none;border:none;padding:0;cursor:pointer;text-decoration:underline"
                        >
                          ↗ Download
                        </button>
                      </div>
                    </div>
                  </div>
                );
              }}
            </For>
          </div>
        </div>
      </Show>

      {/* ── Image Lightbox ── */}
      <Show when={lightbox()}>
        <div
          style="position:fixed;inset:0;background:rgba(0,0,0,.85);z-index:9999;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20px"
          onClick={() => setLightbox(null)}
        >
          <div style="display:flex;align-items:center;justify-content:space-between;width:100%;max-width:900px;margin-bottom:12px">
            <span style="color:#f8fafc;font-size:14px;font-weight:600">{lightbox()!.label}</span>
            <div style="display:flex;gap:10px">
              <a href={lightbox()!.src} target="_blank" rel="noreferrer"
                 style="color:#93c5fd;font-size:13px;text-decoration:underline"
                 onClick={(e) => e.stopPropagation()}>
                ↗ Open original
              </a>
              <button
                type="button"
                style="color:#f8fafc;background:none;border:none;font-size:22px;cursor:pointer;line-height:1"
                onClick={() => setLightbox(null)}
              >
                ✕
              </button>
            </div>
          </div>
          <img
            src={lightbox()!.src}
            alt={lightbox()!.label}
            style="max-width:900px;max-height:80vh;object-fit:contain;border-radius:8px;box-shadow:0 0 40px rgba(0,0,0,.6)"
            onClick={(e) => e.stopPropagation()}
          />
        </div>
      </Show>

      {/* ── PDF Viewer Modal ── */}
      <Show when={pdfViewer()}>
        <div
          style="position:fixed;inset:0;background:rgba(0,0,0,.75);z-index:9999;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20px"
        >
          <div style="background:#fff;border-radius:12px;overflow:hidden;width:100%;max-width:900px;max-height:90vh;display:flex;flex-direction:column;box-shadow:0 25px 60px rgba(0,0,0,.5)">
            {/* Header */}
            <div style="display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid #e2e8f0;background:#f8fafc">
              <span style="font-size:14px;font-weight:600;color:#0f172a">📄 {pdfViewer()!.label}</span>
              <div style="display:flex;gap:8px;align-items:center">
                <a href={pdfViewer()!.src} target="_blank" rel="noreferrer"
                   style="font-size:12px;color:#2563eb;text-decoration:underline">
                  ↗ Open in new tab
                </a>
                <button
                  type="button"
                  class="inline-flex items-center rounded-lg border border-gray-200 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 transition-colors"
                  style="padding:4px 10px;font-size:13px"
                  onClick={() => setPdfViewer(null)}
                >
                  Close
                </button>
              </div>
            </div>
            {/* PDF embed */}
            <iframe
              src={`${pdfViewer()!.src}#toolbar=1&view=FitH`}
              style="flex:1;min-height:600px;width:100%;border:none"
              title={pdfViewer()!.label}
            />
          </div>
        </div>
      </Show>
    </>
  );
}
