<script setup lang="ts">
import { UiIcon } from '@/components/UiIcon';
import { cn } from '@/lib/utils';
import { computed } from 'vue';
import type { UiFileTypeProps, UiFileTypeTone } from './types';

defineOptions({
  name: 'UiFileType',
});

/** @see {@link UiFileTypeProps} */
const props = withDefaults(defineProps<UiFileTypeProps>(), {
  filename: undefined,
  tone: undefined,
  icon: undefined,
  error: false,
  loading: false,
});

/** Visual preset (tone + icon) for a known file extension. */
interface FileTypePreset {
  /** Background tone of the round badge. */
  tone: UiFileTypeTone;
  /** Lucide icon name rendered inside the badge. */
  icon: string;
}

/**
 * File-extension → (tone, icon) presets sourced from the Figma `Filetype`
 * component. Keys are normalized to lower-case, dotless extensions; any
 * extension not listed here falls through to the `default` preset.
 * @see {@link https://www.figma.com/design/SrZQ19QVN1sQkuAMnMC746/AA26--WIP-?node-id=26438-42144}
 */
const FILE_TYPE_PRESETS: Record<string, FileTypePreset> = {
  // Type=Text → accent-pink + file icon.
  pdf: { tone: 'accent-pink', icon: 'file' },
  doc: { tone: 'accent-pink', icon: 'file' },
  docx: { tone: 'accent-pink', icon: 'file' },
  txt: { tone: 'accent-pink', icon: 'file' },
  rtf: { tone: 'accent-pink', icon: 'file' },
  // Type=Markdown → accent-soft + code-xml icon.
  html: { tone: 'accent-soft', icon: 'code-xml' },
  htm: { tone: 'accent-soft', icon: 'code-xml' },
  md: { tone: 'accent-soft', icon: 'code-xml' },
  mdx: { tone: 'accent-soft', icon: 'code-xml' },
  // Type=Tabular → accent-yellow + table-2 icon.
  csv: { tone: 'accent-yellow', icon: 'table-2' },
  tsv: { tone: 'accent-yellow', icon: 'table-2' },
  xls: { tone: 'accent-yellow', icon: 'table-2' },
  xlsx: { tone: 'accent-yellow', icon: 'table-2' },
};

const DEFAULT_PRESET: FileTypePreset = { tone: 'default', icon: 'file' };

/**
 * Lower-case, dotless extension. Returns `''` for files without an
 * extension or for dotfiles like `.gitignore`.
 * @param name - Full file name
 */
function getFileExtension(name: string): string {
  const i = name.lastIndexOf('.');
  if (i <= 0 || i === name.length - 1) return '';
  return name.slice(i + 1).toLowerCase();
}

const filePreset = computed<FileTypePreset>(() => {
  if (!props.filename) return DEFAULT_PRESET;
  const ext = getFileExtension(props.filename);
  return FILE_TYPE_PRESETS[ext] ?? DEFAULT_PRESET;
});

const resolvedTone = computed<UiFileTypeTone>(() => {
  if (props.error || props.loading) return 'default';
  return props.tone || filePreset.value.tone;
});

const resolvedIcon = computed<string>(() => {
  if (props.error) return 'circle-alert';
  return props.icon || filePreset.value.icon;
});

// Tone names map to token-backed background utilities from `tokens.json`.
const TONE_FILL: Record<UiFileTypeTone, string> = {
  default: 'bg-background-surface-muted-subtle',
  'accent-pink': 'bg-background-accent-pink',
  'accent-soft': 'bg-background-accent-soft',
  'accent-yellow': 'bg-background-accent-yellow',
};

const badgeClass = computed(() =>
  cn(
    'flex size-8 shrink-0 items-center justify-center rounded-full text-content-on-surface-primary',
    TONE_FILL[resolvedTone.value],
  ),
);
</script>

<template>
  <div
    data-slot="file-type"
    :data-tone="resolvedTone"
    :class="badgeClass"
    aria-hidden="true"
  >
    <UiIcon
      :name="resolvedIcon"
      :size="16"
      :class="error ? 'text-content-on-status-error-inverse' : undefined"
    />
  </div>
</template>
