import Link from 'next/link';
import { postPath, type Locale, type PostSummary } from '@ai-radar/shared';
import type { Dictionary } from '@/lib/dictionary';
import { CategoryLabel } from '../ui/CategoryLabel';
import { SourceIcon } from '../ui/SourceIcon';
import { TimeAgo } from '../ui/TimeAgo';

/**
 * The four card treatments, and nothing else.
 *
 * Their decreasing visual weight *is* the page hierarchy:
 *   HeroCard      surface + accent rule + serif hero title
 *   StandardCard  surface, no accent, serif card title
 *   CompactCard   border only, no fill, sans title
 *   StoryRow      no card at all, hairline separator
 *
 * A fifth treatment would flatten that, so there isn't one.
 */

interface CardProps {
  post: PostSummary;
  locale: Locale;
  dict: Dictionary;
}

function SourceLine({ post, locale, dict }: CardProps) {
  return (
    <div className="card-foot">
      {post.worthTrying === 'yes' && (
        <span className="worth">
          <TickIcon /> {dict.home.worthTrying}
        </span>
      )}
      {/* Only the title links to our story page, so this outbound link
          needs no click handling to escape a wrapping anchor. */}
      <a href={post.sourceUrl} target="_blank" rel="noopener noreferrer" className="source-link">
        {hostOf(post.sourceUrl)} <span className="arrow">↗</span>
      </a>
      {post.sourceCount > 1 && (
        <span className="t-meta">
          <span className="dot-sep">·</span> {post.sourceCount} {dict.meta.sources}
        </span>
      )}
    </div>
  );
}

function WhyItMatters({
  text,
  dict,
  small = false,
}: {
  text: string;
  dict: Dictionary;
  small?: boolean;
}) {
  if (!text) return null;
  return (
    <div className="why">
      <div className="why-label">{dict.story.whyItMatters}</div>
      <p className={`why-text ${small ? 't-body-sm' : 't-body'}`}>{text}</p>
    </div>
  );
}

function MetaLine({ post, locale }: { post: PostSummary; locale: Locale }) {
  // The icon identifies the company named next to it, so it is shown only
  // alongside that name — on its own it would be an unlabelled badge.
  return (
    <span className="t-meta meta-line">
      {post.companyName && (
        <>
          <SourceIcon src={post.sourceIconUrl} size={20} />
          {post.companyName} <span className="dot-sep">·</span>{' '}
        </>
      )}
      <TimeAgo date={post.publishedAt} locale={locale} />
    </span>
  );
}

/** Tier 2. One per page. The only card with both a surface and an accent. */
export function HeroCard({ post, locale, dict }: CardProps) {
  return (
    <article className="card-hero">
      <div className="card-head">
        <CategoryLabel category={post.category} locale={locale} sponsored={post.sponsored} />
        <MetaLine post={post} locale={locale} />
      </div>

      <Link href={postPath(post.category, post.slug, locale)}>
        <h2 className="t-hero card-title">{post.title}</h2>
      </Link>

      <p className="card-summary t-body" style={{ marginTop: 'var(--s4)' }}>
        {post.summary}
      </p>

      <div style={{ marginTop: 'var(--s4)' }}>
        <WhyItMatters text={post.whyItMatters} dict={dict} />
      </div>

      <SourceLine post={post} locale={locale} dict={dict} />
    </article>
  );
}

/** Tier 3. Two up on desktop. Surface, no accent. */
export function StandardCard({ post, locale, dict }: CardProps) {
  return (
    <article className="card-std">
      <div className="card-head">
        <CategoryLabel category={post.category} locale={locale} sponsored={post.sponsored} />
        <MetaLine post={post} locale={locale} />
      </div>

      <Link href={postPath(post.category, post.slug, locale)}>
        <h3 className="t-card-lg card-title">{post.title}</h3>
      </Link>

      <p className="card-summary t-body-sm">{post.summary}</p>

      <WhyItMatters text={post.whyItMatters} dict={dict} small />

      <SourceLine post={post} locale={locale} dict={dict} />
    </article>
  );
}

/** Tier 4. Three or four up. Border only, no fill. */
export function CompactCard({ post, locale, dict }: CardProps) {
  return (
    <article className="card-compact">
      <div className="card-head">
        <CategoryLabel category={post.category} locale={locale} sponsored={post.sponsored} />
        <TimeAgo date={post.publishedAt} locale={locale} className="t-meta" />
      </div>

      <Link href={postPath(post.category, post.slug, locale)}>
        <h3 className="t-card card-title">{post.title}</h3>
      </Link>

      <p className="card-summary t-body-sm" style={{ marginBottom: 'var(--s2)' }}>
        {truncate(post.summary, 110)}
      </p>

      {post.worthTrying === 'yes' && (
        <div className="card-foot">
          <span className="worth">
            <TickIcon /> {dict.home.worthTrying}
          </span>
        </div>
      )}
    </article>
  );
}

/**
 * Tier 5. No card, no fill, no border — a hairline separator only.
 * Dense update feeds read better as editorial rows than as boxes.
 */
export function StoryRow({ post, locale }: { post: PostSummary; locale: Locale }) {
  return (
    <li className="story-row">
      <Link href={postPath(post.category, post.slug, locale)}>
        <TimeAgo date={post.publishedAt} locale={locale} className="row-time" />
        <CategoryLabel category={post.category} locale={locale} sponsored={post.sponsored} />
        <span className="t-row">{post.title}</span>
        <span className="source-link">{hostOf(post.sourceUrl)}</span>
      </Link>
    </li>
  );
}

// ------------------------------------------------------------- helpers

function TickIcon() {
  return (
    <svg width="11" height="11" viewBox="0 0 12 12" fill="none" aria-hidden="true">
      <path
        d="M2.5 6.5 4.75 8.75 9.5 3.5"
        stroke="currentColor"
        strokeWidth="1.7"
        strokeLinecap="round"
        strokeLinejoin="round"
      />
    </svg>
  );
}

function hostOf(url: string): string {
  try {
    return new URL(url).hostname.replace(/^www\./, '');
  } catch {
    return 'source';
  }
}

function truncate(text: string, max: number): string {
  if (text.length <= max) return text;
  // Cut on a word boundary so the ellipsis does not land mid-word. Works
  // for Arabic too, which also separates words with spaces.
  const cut = text.slice(0, max);
  const lastSpace = cut.lastIndexOf(' ');
  return `${cut.slice(0, lastSpace > max * 0.6 ? lastSpace : max)}…`;
}
