import { nip19 } from 'nostr-tools';
import { match } from 'path-to-regexp';

import { MastodonAccount } from '@/entities/MastodonAccount.ts';
import { MastodonStatus } from '@/entities/MastodonStatus.ts';
import { InstanceMetadata } from '@/utils/instance.ts';

export interface MetadataEntities {
  status?: MastodonStatus;
  account?: MastodonAccount;
  instance: InstanceMetadata;
}

export interface MetadataPathParams {
  statusId?: string;
  acct?: string;
  bech32?: string;
}

/** URL routes to serve metadata on. */
const SSR_ROUTES = [
  '/\\@:acct/posts/:statusId',
  '/\\@:acct/:statusId',
  '/\\@:acct',
  '/users/:acct/statuses/:statusId',
  '/users/:acct',
  '/statuses/:statusId',
  '/notice/:statusId',
  '/posts/:statusId',
  '/:bech32',
] as const;

const SSR_ROUTE_MATCHERS = SSR_ROUTES.map((route) => match(route));

export function getPathParams(path: string): MetadataPathParams | undefined {
  for (const matcher of SSR_ROUTE_MATCHERS) {
    const result = matcher(path);
    if (!result) continue;

    const params: MetadataPathParams = result.params;

    if (params.bech32) {
      try {
        const decoded = nip19.decode(params.bech32);
        switch (decoded.type) {
          case 'nevent':
            params.statusId = decoded.data.id;
            break;
          case 'note':
            params.statusId = decoded.data;
            break;
          case 'nprofile':
            params.acct = decoded.data.pubkey;
            break;
          case 'npub':
            params.acct = decoded.data;
            break;
        }
      } catch {
        // fall through
      }
    }

    return params;
  }
}
