/// Card: number / holder / expiry MonthYear / cvv / pin / kind.
/// Detail view has a styled card-silhouette signature block.

import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab } from '../../../shared/state';
import { renderFormHeader } from '../form-header';
import { REQUIRED_PILL_HTML } from '../../../shared/glyphs';
import type { Item, ItemId, ManifestEntry, CardKind, Section, AttachmentRef } from '../../../shared/types';
import {
  renderConcealedRow, renderSignatureBlock, wireFieldHandlers, renderSections,
  renderSectionsEditor, wireSectionsEditor,
} from '../fields';
import {
  renderAttachmentsDisclosure,
  wireAttachmentsDisclosure,
  teardownAttachmentsDisclosure,
} from '../attachments-disclosure';

const CARD_KINDS: CardKind[] = ['credit', 'debit', 'gift', 'loyalty', 'other'];

let activeKeyHandler: ((e: KeyboardEvent) => void) | null = null;
let activeFormEscHandler: ((e: KeyboardEvent) => void) | null = null;
let sectionsExpanded = false;

export function teardown(): void {
  teardownAttachmentsDisclosure();
  if (activeKeyHandler) {
    document.removeEventListener('keydown', activeKeyHandler);
    activeKeyHandler = null;
  }
  if (activeFormEscHandler) {
    document.removeEventListener('keydown', activeFormEscHandler);
    activeFormEscHandler = null;
  }
  sectionsExpanded = false;
}

function brandFromNumber(num: string): string {
  if (/^3[47]/.test(num))  return 'AMEX';
  if (/^4/.test(num))      return 'VISA';
  if (/^5[1-5]/.test(num)) return 'MASTERCARD';
  if (/^6/.test(num))      return 'DISCOVER';
  return '';
}

function maskedNumber(num: string): string {
  if (!num) return '';
  const last4 = num.slice(-4);
  const groups = num.length > 4 ? '•••• •••• •••• ' : '';
  return `${groups}${last4}`;
}

function formatExpiry(e: { month: number; year: number } | undefined): string {
  if (!e) return '';
  const mm = String(e.month).padStart(2, '0');
  const yy = String(e.year).slice(-2);
  return `${mm}/${yy}`;
}

export async function renderDetail(app: HTMLElement, item: Item): Promise<void> {
  if (item.core.type !== 'card') return;
  const c = item.core;
  const number = c.number ?? '';
  const brand = brandFromNumber(number);
  const kindLabel = (c.kind ?? 'other').toUpperCase();
  const bandLabel = brand ? `${brand} · ${kindLabel}` : kindLabel;

  const sigInner = `
    <div style="font-size:9px;letter-spacing:0.1em;color:#6e7681;margin-bottom:6px;">${escapeHtml(bandLabel)}</div>
    <div style="font-family:monospace;font-size:14px;letter-spacing:0.08em;color:#c9d1d9;margin-bottom:12px;display:flex;justify-content:space-between;align-items:center;" data-field-id="card-number" data-revealed="false" data-field-value="${escapeHtml(number)}" data-field-multiline="false">
      <span data-field-role="value">${escapeHtml(maskedNumber(number))}</span>
      ${number ? '<button type="button" data-field-action="reveal" style="font-size:10px;color:#8b949e;cursor:pointer;font-family:system-ui,sans-serif;letter-spacing:0;background:transparent;border:0;">show</button>' : ''}
    </div>
    <div style="display:flex;justify-content:space-between;align-items:flex-end;">
      <div>
        <div style="font-size:9px;color:#6e7681;letter-spacing:0.08em;">HOLDER</div>
        <div style="font-size:11px;color:#c9d1d9;">${escapeHtml(c.holder ?? '')}</div>
      </div>
      <div style="text-align:right;">
        <div style="font-size:9px;color:#6e7681;letter-spacing:0.08em;">EXPIRES</div>
        <div style="font-family:monospace;font-size:11px;color:#c9d1d9;">${escapeHtml(formatExpiry(c.expiry))}</div>
      </div>
    </div>
  `;

  app.innerHTML = `
    <div class="pad">
      <div style="margin-bottom:12px;">
        <div class="detail-title" style="margin-bottom:8px;">${escapeHtml(item.title)}</div>
        ${renderSignatureBlock({ accent: 'gold', children: sigInner })}
      </div>
      ${c.cvv ? renderConcealedRow({ id: 'card-cvv', label: 'cvv', value: c.cvv, monospace: true }) : ''}
      ${c.pin ? renderConcealedRow({ id: 'card-pin', label: 'pin', value: c.pin, monospace: true }) : ''}
      ${renderSections(item, 'card')}
      ${renderAttachmentsDisclosure({ itemId: item.id, attachments: item.attachments, mode: 'view' })}
      <div class="form-actions" style="margin-top:14px;">
        <button class="btn" id="back-btn">back</button>
        <button class="btn" id="edit-btn">edit</button>
        <button class="btn danger" id="trash-btn">trash</button>
      </div>
    </div>
  `;

  // The card-number reveal lives inside the signature block, so wireFieldHandlers
  // picks it up alongside the cvv/pin rows.
  wireFieldHandlers(app);
  wireAttachmentsDisclosure(app, { itemId: item.id, attachments: item.attachments, mode: 'view' });

  document.getElementById('back-btn')?.addEventListener('click', () => { teardown(); navigate('list'); });
  document.getElementById('edit-btn')?.addEventListener('click', () => { teardown(); navigate('edit'); });
  document.getElementById('trash-btn')?.addEventListener('click', async () => {
    if (!confirm(`Move "${item.title}" to trash?`)) return;
    teardown();
    const resp = await sendMessage({ type: 'delete_item', id: item.id });
    if (!resp.ok) { setState({ error: resp.error }); return; }
    const listResp = await sendMessage({ type: 'list_items' });
    if (listResp.ok) {
      const data = listResp.data as { items: Array<[ItemId, ManifestEntry]> };
      navigate('list', { entries: data.items, selectedId: null, selectedItem: null });
    } else navigate('list');
  });

  const handler = async (e: KeyboardEvent) => {
    const t = e.target;
    if (t instanceof HTMLElement) {
      const tag = t.tagName;
      if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || t.isContentEditable) return;
    }
    switch (e.key) {
      case 'Escape': teardown(); navigate('list'); break;
      case 'e':      teardown(); navigate('edit'); break;
      case 'd':
        e.preventDefault();
        if (confirm(`Move "${item.title}" to trash?`)) {
          teardown();
          const resp = await sendMessage({ type: 'delete_item', id: item.id });
          if (!resp.ok) { setState({ error: resp.error }); return; }
          const listResp = await sendMessage({ type: 'list_items' });
          if (listResp.ok) {
            const data = listResp.data as { items: Array<[ItemId, ManifestEntry]> };
            navigate('list', { entries: data.items, selectedId: null, selectedItem: null });
          } else navigate('list');
        }
        break;
    }
  };
  activeKeyHandler = handler;
  document.addEventListener('keydown', handler);
}

export function renderForm(app: HTMLElement, mode: 'add' | 'edit', existing: Item | null): void {
  const state = getState();
  const title = existing?.title ?? '';
  const c = (existing?.core.type === 'card') ? existing.core : null;
  const currentYear = new Date().getFullYear();

  const sectionsDraft: Section[] = existing
    ? JSON.parse(JSON.stringify(existing.sections)) as Section[]
    : [];
  let attachmentsDraft: AttachmentRef[] = existing?.attachments ?? [];

  const monthOptions = Array.from({ length: 12 }, (_, i) => {
    const m = String(i + 1).padStart(2, '0');
    const sel = c?.expiry?.month === i + 1 ? 'selected' : '';
    return `<option value="${m}" ${sel}>${m}</option>`;
  }).join('');
  const yearOptions = Array.from({ length: 51 }, (_, i) => {
    const y = currentYear - 25 + i;
    const sel = c?.expiry?.year === y ? 'selected' : '';
    return `<option value="${y}" ${sel}>${y}</option>`;
  }).join('');
  const kindOptions = CARD_KINDS.map((k) => {
    const sel = (c?.kind ?? 'credit') === k ? 'selected' : '';
    return `<option value="${k}" ${sel}>${k}</option>`;
  }).join('');

  app.innerHTML = `
    <div class="pad">
      ${renderFormHeader({ titleText: mode === 'add' ? 'new card' : 'edit card' })}
      ${state.error ? `<div class="error">${escapeHtml(state.error)}</div>` : ''}
      <div class="form-group"><label class="label" for="f-title">title ${REQUIRED_PILL_HTML}</label>
        <input id="f-title" type="text" value="${escapeHtml(title)}" placeholder="Amex Gold"></div>
      <div class="form-group"><label class="label" for="f-number">number</label>
        <input id="f-number" type="text" inputmode="numeric" value="${escapeHtml(c?.number ?? '')}" placeholder="378282246310005"></div>
      <div class="form-group"><label class="label" for="f-holder">holder</label>
        <input id="f-holder" type="text" value="${escapeHtml(c?.holder ?? '')}" placeholder="AARON LEE"></div>
      <div class="form-group"><label class="label">expiry</label>
        <div class="inline-row">
          <select id="f-expiry-month"><option value="">mm</option>${monthOptions}</select>
          <select id="f-expiry-year"><option value="">yyyy</option>${yearOptions}</select>
        </div></div>
      <div class="form-group"><label class="label" for="f-cvv">cvv</label>
        <input id="f-cvv" type="password" inputmode="numeric" maxlength="4" value="${escapeHtml(c?.cvv ?? '')}"></div>
      <div class="form-group"><label class="label" for="f-pin">pin</label>
        <input id="f-pin" type="password" inputmode="numeric" maxlength="8" value="${escapeHtml(c?.pin ?? '')}"></div>
      <div class="form-group"><label class="label" for="f-kind">kind</label>
        <select id="f-kind">${kindOptions}</select></div>
      ${renderSectionsEditor(sectionsDraft, sectionsExpanded)}
      ${renderAttachmentsDisclosure({ itemId: existing?.id ?? '', attachments: attachmentsDraft, mode: 'edit' })}
      <div class="form-actions">
        <button class="btn" id="cancel-btn">cancel</button>
        <button class="btn btn-primary" id="save-btn">save</button>
      </div>
    </div>
  `;

  const rerender = (): void => {
    const disclosure = app.querySelector('.disclosure');
    if (!disclosure) return;
    sectionsExpanded = disclosure.getAttribute('data-expanded') === 'true';
    disclosure.outerHTML = renderSectionsEditor(sectionsDraft, sectionsExpanded);
    wireSectionsEditor(app, sectionsDraft, rerender);
  };
  wireSectionsEditor(app, sectionsDraft, rerender);

  const wireDisclosure = (): void => {
    wireAttachmentsDisclosure(app, {
      itemId: existing?.id ?? '',
      attachments: attachmentsDraft,
      mode: 'edit',
      onChange: (next) => {
        attachmentsDraft = next;
        const disc = app.querySelector('.attachments-disclosure');
        if (disc) {
          disc.outerHTML = renderAttachmentsDisclosure({
            itemId: existing?.id ?? '',
            attachments: attachmentsDraft,
            mode: 'edit',
          });
          wireDisclosure();
        }
      },
    });
  };
  wireDisclosure();

  document.getElementById('cancel-btn')?.addEventListener('click', () => {
    setState({ error: null });
    navigate(mode === 'edit' ? 'detail' : 'list');
  });
  document.getElementById('popout-btn')?.addEventListener('click', popOutToTab);
  document.getElementById('save-btn')?.addEventListener('click', async () => {
    await saveCard(mode, existing, sectionsDraft, attachmentsDraft);
  });

  const escHandler = (e: KeyboardEvent) => {
    if (e.key === 'Escape') {
      setState({ error: null });
      navigate(mode === 'edit' ? 'detail' : 'list');
    }
  };
  activeFormEscHandler = escHandler;
  document.addEventListener('keydown', escHandler);

  (document.getElementById('f-title') as HTMLInputElement | null)?.focus();
}

async function saveCard(mode: 'add' | 'edit', existing: Item | null, sectionsDraft: Section[], attachmentsDraft: AttachmentRef[]): Promise<void> {
  const state = getState();
  const title = (document.getElementById('f-title') as HTMLInputElement).value.trim();
  if (!title) { setState({ error: 'Title is required' }); return; }

  const get = (id: string) => (document.getElementById(id) as HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement).value.trim();
  const number = get('f-number');
  const holder = get('f-holder');
  const expMonth = get('f-expiry-month');
  const expYear  = get('f-expiry-year');
  const cvv = get('f-cvv');
  const pin = get('f-pin');
  const kindRaw = get('f-kind');
  const kind: CardKind = (CARD_KINDS as string[]).includes(kindRaw) ? (kindRaw as CardKind) : 'credit';

  const expiry = (expMonth && expYear)
    ? { month: Number(expMonth), year: Number(expYear) }
    : undefined;

  const core = {
    type: 'card' as const,
    number: number || undefined,
    holder: holder || undefined,
    expiry,
    cvv: cvv || undefined,
    pin: pin || undefined,
    kind,
  };

  const now = Math.floor(Date.now() / 1000);
  const item: Item = {
    id: existing?.id ?? '',
    title, type: 'card',
    tags: existing?.tags ?? [],
    favorite: existing?.favorite ?? false,
    group: existing?.group, notes: existing?.notes,
    created: existing?.created ?? now,
    modified: now, trashed_at: undefined,
    core,
    sections: sectionsDraft,
    attachments: attachmentsDraft,
    field_history: existing?.field_history ?? {},
  };

  setState({ loading: true, error: null });
  const resp = mode === 'add'
    ? await sendMessage({ type: 'add_item', item })
    : await sendMessage({ type: 'update_item', id: state.selectedId!, item });
  if (resp.ok) {
    const listResp = await sendMessage({ type: 'list_items' });
    if (listResp.ok) {
      const data = listResp.data as { items: Array<[ItemId, ManifestEntry]> };
      navigate('list', { entries: data.items, selectedId: null, selectedItem: null });
    } else navigate('list');
  } else {
    setState({ loading: false, error: resp.error });
  }
}
