import { createDirectus, rest, readSingleton, readItems, readItem, staticToken } from '@directus/sdk';

// Types alignes sur le schema cree par scripts/seed-directus.mjs

export interface SiteSettings {
  studio_name: string;
  city: string;
  region: string;
  country: string;
  coords: string;
  email: string;
  est_year: number;
  current_year: number;
  hero_tag: string;
  hero_display_lines: string[];
  hero_italic_line: string;
  hero_lede: string;
  hero_stat: string;
  hero_year_prefix: string;
  hero_year_suffix: string;
  manifesto_tag: string;
  manifesto_italic: string;
  manifesto_end: string;
  manifesto_paragraphs: string[];
  pricing_categories: Array<{
    num: string;
    name: string;
    slug: string;
    startsAt: string;
    formules: string;
  }>;
  contact_title: string;
  contact_body: string;
  contact_addr: string;
}

export type SerieCategory = 'mariage' | 'portrait-lifestyle' | 'reportage-editorial' | 'evenementiel';
export type SerieFormule = 'demi-journee' | 'journee-complete' | 'sur-mesure';

export interface Serie {
  id: string;
  status: 'published' | 'draft' | 'archived';
  sort: number | null;
  index: number;
  category: SerieCategory;
  title: string;
  lieu: string;
  date_shoot: string;
  cover: string | null;
  cover_alt: string;
  excerpt: string;
  couple: string | null;
  invites: number | null;
  formule: SerieFormule | null;
  client: string | null;
  duree: string | null;
  published: boolean;
  gallery: string[];
}

interface Schema {
  site_settings: SiteSettings;
  series: Serie[];
}

const URL =
  import.meta.env.DIRECTUS_URL ||
  process.env.DIRECTUS_URL ||
  'http://localhost:8055';
const TOKEN =
  import.meta.env.DIRECTUS_TOKEN ||
  process.env.DIRECTUS_TOKEN ||
  '';

const client = TOKEN
  ? createDirectus<Schema>(URL).with(staticToken(TOKEN)).with(rest())
  : createDirectus<Schema>(URL).with(rest());

// Fallback values used when Directus is unreachable or returns nothing.
// Permet au dev de fonctionner sans Directus running.
const FALLBACK_SETTINGS: SiteSettings = {
  studio_name: 'Mostuki Photo',
  city: 'CANNES',
  region: 'PACA',
  country: 'FR',
  coords: '43.55N 7.02E',
  email: 'corentin.jog@gmail.com',
  est_year: 2018,
  current_year: 2026,
  hero_tag: '[01] STUDIO.',
  hero_display_lines: ['STUDIO PHOTO.', 'CANNES / PACA.'],
  hero_italic_line: 'documentaire.',
  hero_lede: 'MARIAGE / PORTRAIT / REPORTAGE / EVENEMENTIEL. UNE METHODE EDITORIALE ET DOCUMENTAIRE QUI VAUT POUR TOUS LES TERRAINS.',
  hero_stat: 'ON OBSERVE · ON ENREGISTRE · ON DERANGE PEU',
  hero_year_prefix: '20',
  hero_year_suffix: '26',
  manifesto_tag: '[02] MANIFESTE.',
  manifesto_italic: 'moins de poses,',
  manifesto_end: 'PLUS DE REGARDS.',
  manifesto_paragraphs: [
    "STUDIO PHOTO BASE A CANNES, COUVERTURE PACA ET PARTOUT EN FRANCE. APPROCHE DOCUMENTAIRE : ON OBSERVE, ON ENREGISTRE, ON DERANGE PEU.",
    "QUATRE TERRAINS, UNE METHODE : MARIAGE, PORTRAIT / LIFESTYLE, REPORTAGE / EDITORIAL, EVENEMENTIEL. LE STYLE NE CHANGE PAS AVEC LE SUJET.",
  ],
  pricing_categories: [
    { num: '01', name: 'MARIAGE', slug: 'mariage', startsAt: '1 200€', formules: 'DEMI-JOURNEE / JOURNEE / SUR-MESURE' },
    { num: '02', name: 'PORTRAIT / LIFESTYLE', slug: 'portrait', startsAt: '400€', formules: 'SEANCE 1H / ETENDU / SUR-MESURE' },
    { num: '03', name: 'REPORTAGE / EDITORIAL', slug: 'reportage', startsAt: '500€', formules: 'DEMI-JOURNEE / JOURNEE / PROJET' },
    { num: '04', name: 'EVENEMENTIEL', slug: 'evenementiel', startsAt: '700€', formules: '2H / DEMI-JOURNEE / JOURNEE' },
  ],
  contact_title: 'ON SE PARLE ?',
  contact_body: "DECRIS-MOI TON PROJET EN QUELQUES LIGNES : TYPE DE SHOOT, DATE APPROXIMATIVE, LIEU, BUDGET INDICATIF. REPONSE SOUS 48H.",
  contact_addr: 'STUDIO MOSTUKI · CANNES · FR',
};

export async function getSiteSettings(): Promise<SiteSettings> {
  try {
    const data = await client.request(readSingleton('site_settings'));
    return { ...FALLBACK_SETTINGS, ...(data as Partial<SiteSettings>) };
  } catch (e) {
    if (import.meta.env?.DEV) {
      console.warn('[directus] site_settings fallback (', (e as Error).message?.split('\n')[0], ')');
    }
    return FALLBACK_SETTINGS;
  }
}

// Normalise la gallery M2M en array d'UUIDs (Directus retourne
// [{ directus_files_id: 'uuid' }, ...] tant que le champ existe).
function normalizeGallery(raw: unknown): string[] {
  if (!Array.isArray(raw)) return [];
  return raw
    .map((item) => {
      if (typeof item === 'string') return item;
      if (item && typeof item === 'object' && 'directus_files_id' in item) {
        const v = (item as { directus_files_id: unknown }).directus_files_id;
        return typeof v === 'string' ? v : null;
      }
      return null;
    })
    .filter((v): v is string => !!v);
}

const SERIE_FIELDS = ['*', { gallery: ['directus_files_id'] }] as const;

export async function getPublishedSeries(): Promise<Serie[]> {
  try {
    const data = await client.request(
      readItems('series', {
        filter: { status: { _eq: 'published' }, published: { _eq: true } },
        sort: ['sort', 'index'],
        limit: -1,
        fields: SERIE_FIELDS as unknown as string[],
      })
    );
    return (data as Array<Record<string, unknown>>).map((d) => ({
      ...(d as unknown as Serie),
      gallery: normalizeGallery(d.gallery),
    }));
  } catch (e) {
    if (import.meta.env?.DEV) {
      console.warn('[directus] series fallback (', (e as Error).message?.split('\n')[0], ')');
    }
    return [];
  }
}

export async function getSerieById(id: string | number): Promise<Serie | null> {
  try {
    const data = await client.request(
      readItem('series', id as never, {
        fields: SERIE_FIELDS as unknown as string[],
      })
    );
    if (!data) return null;
    const d = data as Record<string, unknown>;
    return {
      ...(d as unknown as Serie),
      gallery: normalizeGallery(d.gallery),
    };
  } catch (e) {
    if (import.meta.env?.DEV) {
      console.warn('[directus] getSerieById fallback (', (e as Error).message?.split('\n')[0], ')');
    }
    return null;
  }
}

export function fileUrl(fileId: string | null | undefined, params: Record<string, string | number> = {}): string {
  if (!fileId) return '';
  // Passe par le proxy Astro /api/files/[id] qui utilise le token admin.
  // Permet de servir des images Directus sans config publique cote Directus.
  const query = new URLSearchParams(
    Object.entries(params).map(([k, v]) => [k, String(v)])
  ).toString();
  return `/api/files/${fileId}${query ? `?${query}` : ''}`;
}
