import { useState, useEffect } from 'react';
import { getTransaction, formatToshis } from '../lib/api';
import type { Transaction } from '../lib/api';
import { Stack, Divider } from './ui/Layout';
import {
  Terminal,
  Section,
  LabelValue,
  DataTable,
  DataRow,
  ActionBar,
  Message,
} from './ui/Terminal';

interface Props {
  txId: string;
}

const handleCache = new Map<string, string>();

async function resolveHandle(did: string): Promise<string> {
  if (handleCache.has(did)) {
    return handleCache.get(did)!;
  }

  try {
    // For did:web, extract the domain directly
    if (did.startsWith('did:web:')) {
      const domain = did.replace('did:web:', '');
      handleCache.set(did, domain);
      return domain;
    }

    // For did:plc, use PLC directory
    if (did.startsWith('did:plc:')) {
      const didRes = await fetch(`https://plc.directory/${did}`);
      if (didRes.ok) {
        const doc = await didRes.json();
        const handle = doc.alsoKnownAs?.[0]?.replace('at://', '') || did;
        handleCache.set(did, handle);
        return handle;
      }
    }
  } catch {
    // Fall back to DID
  }

  handleCache.set(did, did);
  return did;
}

export default function TransactionDetail({ txId }: Props) {
  const [tx, setTx] = useState<Transaction | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [resolvedHandles, setResolvedHandles] = useState<Map<string, string>>(new Map());

  useEffect(() => {
    async function fetchTx() {
      try {
        const result = await getTransaction(txId);
        setTx(result.transaction);

        const dids = new Set<string>();
        result.transaction.outputs.forEach(o => dids.add(o.owner));
        // Handle both trigger types
        const trigger = result.transaction.trigger;
        if (trigger) {
          if ('followerDid' in trigger) {
            dids.add(trigger.followerDid);
          } else if ('senderDid' in trigger) {
            dids.add(trigger.senderDid);
          }
        }

        const handles = new Map<string, string>();
        await Promise.all(
          Array.from(dids).map(async did => {
            const handle = await resolveHandle(did);
            handles.set(did, handle);
          })
        );
        setResolvedHandles(handles);
      } catch (e) {
        setError(e instanceof Error ? e.message : 'Failed to fetch transaction');
      } finally {
        setLoading(false);
      }
    }
    fetchTx();
  }, [txId]);

  if (loading) {
    return (
      <Terminal title="TRANSACTION">
        <Section>
          <LabelValue label="STATUS" value="LOADING..." status="warning" />
        </Section>
      </Terminal>
    );
  }

  if (error || !tx) {
    return (
      <Terminal title="TRANSACTION NOT FOUND">
        <Section>
          <Stack gap="sm">
            <LabelValue label="TXID" value={txId} />
            <Message type="error">{error || 'Transaction not found'}</Message>
          </Stack>
        </Section>
        <Divider />
        <ActionBar>
          <a href="/wallet" className="btn secondary">[BACK TO WALLET]</a>
          <a href="/" className="btn secondary">[HOME]</a>
        </ActionBar>
      </Terminal>
    );
  }

  const formatDid = (did: string) => {
    const handle = resolvedHandles.get(did);
    if (handle && handle !== did) {
      return `@${handle}`;
    }
    return did.length > 32 ? `${did.slice(0, 32)}...` : did;
  };

  const totalOutput = tx.outputs.reduce((sum, o) => sum + o.amount, 0);

  return (
    <Terminal title="TRANSACTION DETAILS">
      <Section title="INFO">
        <Stack gap="xs">
          <LabelValue label="TXID" value={txId} />
          <LabelValue label="TYPE" value={tx.type.toUpperCase()} />
          <LabelValue label="DATE" value={new Date(tx.createdAt).toLocaleString()} />
          {tx.trigger && 'followerDid' in tx.trigger && (
            <>
              <LabelValue label="TRIGGER" value="Follow event" />
              <LabelValue label="FROM" value={formatDid((tx.trigger as { followerDid: string }).followerDid)} />
            </>
          )}
          {tx.trigger && 'type' in tx.trigger && (tx.trigger as { type: string }).type === 'cashtag' && (
            <>
              <LabelValue label="TRIGGER" value="$attoshi cashtag" />
              <LabelValue label="FROM" value={formatDid((tx.trigger as { senderDid: string }).senderDid)} />
            </>
          )}
        </Stack>
      </Section>

      <Divider />

      <Section title="RECIPIENTS">
        <DataTable
          headers={['#', 'AMOUNT', 'TO']}
          widths={['2rem', '8rem', '1fr']}
        >
          {tx.outputs.map((output, i) => (
            <DataRow
              key={i}
              cells={[
                String(i + 1),
                `${formatToshis(output.amount)} @toshis`,
                formatDid(output.owner),
              ]}
              widths={['2rem', '8rem', '1fr']}
            />
          ))}
        </DataTable>
        <LabelValue
          label="TOTAL"
          value={`${formatToshis(totalOutput)} @toshis`}
        />
      </Section>

      {tx.type === 'transfer' && tx.inputs.length > 0 && (
        <>
          <Divider />
          <Section title="SPENT COINS">
            <DataTable
              headers={['#', 'SOURCE TX']}
              widths={['2rem', '1fr']}
            >
              {tx.inputs.map((input, i) => (
                <DataRow
                  key={i}
                  cells={[
                    String(i + 1),
                    `${input.txId}:${input.index}`,
                  ]}
                  widths={['2rem', '1fr']}
                />
              ))}
            </DataTable>
          </Section>
        </>
      )}

      <Divider />

      <ActionBar>
        <a href="/wallet" className="btn secondary">[BACK TO WALLET]</a>
        <a href="/" className="btn secondary">[HOME]</a>
      </ActionBar>
    </Terminal>
  );
}
