import { Ionicons } from '@expo/vector-icons';
import { Image } from 'expo-image';
import { useFocusEffect, useLocalSearchParams, useRouter } from 'expo-router';
import { useCallback, useEffect, useState } from 'react';
import { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';

import { Button, ErrorNote, Field } from '@/components/ui';
import {
  TYPEN,
  VARIANTEN_JE_MODELL,
  jobsZuAsset,
  neueRunde,
  varianteWiederholen,
  versionFreigeben,
  versionenZuAsset,
  type Asset,
  type AssetVersion,
  type VariantenLage,
} from '@/lib/assets';
import { useSession } from '@/lib/session';
import { fehlertext } from '@/lib/auth';
import { useBildQuelle } from '@/lib/bildquelle';
import { BUCKET_BILDER, BUCKET_REFERENZEN } from '@/lib/dateien';
import { databaseId, tables } from '@/lib/appwrite';
import { colors, radius, space, text } from '@/theme/tokens';

export default function ModellErgebnisScreen() {
  const { id } = useLocalSearchParams<{ id: string }>();
  const router = useRouter();

  const { brand } = useSession();
  const [asset, setAsset] = useState<Asset | null>(null);
  const [versionen, setVersionen] = useState<AssetVersion[]>([]);
  const [lagen, setLagen] = useState<Map<string, VariantenLage>>(new Map());
  const [fehler, setFehler] = useState<string | null>(null);
  const [busy, setBusy] = useState<string | null>(null);
  const [grund, setGrund] = useState('');

  const laden = useCallback(async () => {
    if (!id) return;
    try {
      const a = (await tables.getRow({ databaseId, tableId: 'assets', rowId: id })) as unknown as Asset;
      setAsset(a);
      const [vs, js] = await Promise.all([versionenZuAsset(id), jobsZuAsset(id)]);
      setVersionen(vs.sort((x, y) => x.version_no - y.version_no));
      setLagen(js);
    } catch (e) {
      setFehler(fehlertext(e));
    }
  }, [id]);

  useFocusEffect(
    useCallback(() => {
      void laden();
    }, [laden]),
  );

  // Solange Varianten offen sind, selbst nachladen – der Dispatcher läuft
  // außerhalb der App, es gibt also nichts, was den Screen sonst aufweckt.
  const offeneJobs = versionen.some(
    (v) => !v.bild_file_id && ['wartend', 'laeuft'].includes(lagen.get(v.$id)?.status ?? 'wartend'),
  );
  useEffect(() => {
    if (!offeneJobs) return;
    const t = setInterval(() => void laden(), 5000);
    return () => clearInterval(t);
  }, [offeneJobs, laden]);

  async function rundeStarten() {
    if (!brand?.team_id || !asset) return;
    const vorlage = versionen[versionen.length - 1];
    setBusy('runde');
    setFehler(null);
    try {
      await neueRunde(brand.$id, brand.team_id, asset.$id, {
        beschreibung: vorlage?.beschreibung_md ?? '',
        merkmale: vorlage?.merkmale ?? [],
        grund: grund.trim(),
      });
      setGrund('');
      await laden();
    } catch (e) {
      setFehler(fehlertext(e));
    } finally {
      setBusy(null);
    }
  }

  async function wiederholen(version: AssetVersion) {
    if (!brand?.team_id || !asset) return;
    setBusy(version.$id);
    try {
      await varianteWiederholen(brand.$id, brand.team_id, asset.$id, version.$id, version.version_no);
      await laden();
    } catch (e) {
      setFehler(fehlertext(e));
    } finally {
      setBusy(null);
    }
  }

  async function freigeben(versionId: string) {
    if (!asset) return;
    setBusy(versionId);
    setFehler(null);
    try {
      await versionFreigeben(asset.$id, versionId);
      await laden();
    } catch (e) {
      setFehler(fehlertext(e));
    } finally {
      setBusy(null);
    }
  }

  const typTitel = TYPEN.find((t) => t.wert === asset?.typ)?.titel ?? asset?.typ;
  const offen = versionen.filter((v) => v.status === 'entwurf');
  const fertig = versionen.filter((v) => v.bild_file_id).length;
  const referenzen = versionen[0]?.reference_file_ids ?? [];

  return (
    <SafeAreaView style={s.safe} edges={['top', 'left', 'right']}>
      <ScrollView contentContainerStyle={s.body}>
        <Text style={s.titel}>{asset?.name ?? 'Modell'}</Text>
        <Text style={s.unter}>
          {typTitel} · {versionen.length} Version(en) · {fertig} erzeugt
          {asset?.released_version_id ? ' · freigegeben' : ' · noch nichts freigegeben'}
        </Text>

        {fehler ? <ErrorNote message={fehler} /> : null}

        {offen.length > 0 && fertig < versionen.length ? (
          <View style={s.hinweisBox}>
            <Ionicons name="hourglass-outline" size={15} color={colors.gold} />
            <Text style={s.hinweisText}>
              {versionen.length - fertig} Variante(n) stehen noch aus. Der Dispatcher muss laufen:
              {'\n'}
              <Text style={s.mono}>BILD_ANBIETER=stub node scripts/job-dispatcher.mjs</Text>
            </Text>
          </View>
        ) : null}

        <View style={s.abschnitt}>
          <Text style={s.abschnittTitel}>Varianten</Text>
          <Text style={s.erklaerung}>
            Nur eine Version wird verwendet – sie gilt als freigegeben, bis du sie bewusst
            ersetzt. Die übrigen werden archiviert, nicht gelöscht.
          </Text>
          <View style={s.gitter}>
            {versionen.map((v) => (
              <VariantenKachel
                key={v.$id}
                version={v}
                lage={lagen.get(v.$id)}
                freigegeben={v.$id === asset?.released_version_id}
                busy={busy === v.$id}
                aufFreigabe={() => void freigeben(v.$id)}
                aufWiederholen={() => void wiederholen(v)}
              />
            ))}
          </View>
        </View>

        {/* Verbessern-Strecke: eine weitere Runde auf demselben Modell.
            Bei Logos gesperrt – ein freigegebenes Markenzeichen wird nicht
            neu interpretiert (Brand-Regel). */}
        {asset?.typ !== 'logo' ? (
          <View style={s.abschnitt}>
            <Text style={s.abschnittTitel}>Nachschärfen</Text>
            <Text style={s.erklaerung}>
              Erzeugt {VARIANTEN_JE_MODELL} weitere Varianten. Die freigegebene Version bleibt
              gültig, bis du bewusst eine neue wählst.
            </Text>
            <Field
              label="Was soll anders werden?"
              value={grund}
              onChangeText={setGrund}
              placeholder="z. B. weicheres Licht, weniger Kontrast, Blick zur Kamera"
              multiline
              numberOfLines={3}
              style={s.mehrzeilig}
            />
            <Button
              title="Neue Runde erzeugen"
              onPress={() => void rundeStarten()}
              busy={busy === 'runde'}
              disabled={grund.trim().length < 4}
            />
          </View>
        ) : null}

        {referenzen.length > 0 ? (
          <View style={s.abschnitt}>
            <Text style={s.abschnittTitel}>Deine Referenzbilder</Text>
            <Text style={s.erklaerung}>
              Die Vorlagen, aus denen die Merkmale stammen. Sie werden nicht veröffentlicht.
            </Text>
            <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={s.reihe}>
              {referenzen.map((fid) => (
                <Referenz key={fid} fileId={fid} />
              ))}
            </ScrollView>
          </View>
        ) : null}

        <Button title="Zurück" variant="ghost" onPress={() => router.back()} />
      </ScrollView>
    </SafeAreaView>
  );
}

function VariantenKachel({
  version, lage, freigegeben, busy, aufFreigabe, aufWiederholen,
}: {
  version: AssetVersion;
  lage?: VariantenLage;
  freigegeben: boolean;
  busy: boolean;
  aufFreigabe: () => void;
  aufWiederholen: () => void;
}) {
  const quelle = useBildQuelle(version.bild_file_id, BUCKET_BILDER);
  const archiviert = version.status === 'archiviert';
  const gescheitert = !version.bild_file_id && lage?.status === 'fehler';

  const zustand = freigegeben ? 'freigegeben'
    : archiviert ? 'archiviert'
    : gescheitert ? 'fehlgeschlagen'
    : version.bild_file_id ? 'Entwurf'
    : 'wird erzeugt';

  return (
    <View style={[s.kachel, archiviert ? s.kachelAus : null]}>
      <View style={[s.rahmen, freigegeben ? s.rahmenFrei : null, gescheitert ? s.rahmenFehler : null]}>
        {quelle ? (
          <Image source={quelle} style={s.bild} contentFit="cover" transition={150} />
        ) : (
          <View style={[s.bild, s.bildLeer]}>
            <Ionicons
              name={gescheitert ? 'alert-circle-outline' : 'hourglass-outline'}
              size={18}
              color={gescheitert ? colors.accent : colors.faint}
            />
          </View>
        )}
        {freigegeben ? (
          <View style={s.siegel}>
            <Ionicons name="checkmark" size={12} color="#fff" />
          </View>
        ) : null}
        {/* EU AI Act: die Kennzeichnung gehört sichtbar ans Bild, nicht erst
            in den Export (projekt-uebersicht.md §10). */}
        {version.bild_file_id ? (
          <View style={s.kiChip}>
            <Text style={s.kiChipText}>KI</Text>
          </View>
        ) : null}
      </View>
      <Text style={s.kachelZeile}>v{version.version_no} · {zustand}</Text>

      {gescheitert ? (
        <>
          <Text style={s.fehlerText} numberOfLines={3}>{lage?.error}</Text>
          <Pressable onPress={aufWiederholen} disabled={busy} accessibilityRole="button" style={s.waehlen}>
            <Text style={s.waehlenText}>{busy ? '…' : 'Nochmal'}</Text>
          </Pressable>
        </>
      ) : !freigegeben && version.bild_file_id ? (
        <Pressable onPress={aufFreigabe} disabled={busy} accessibilityRole="button" style={s.waehlen}>
          <Text style={s.waehlenText}>{busy ? '…' : 'Diese nehmen'}</Text>
        </Pressable>
      ) : null}
    </View>
  );
}

function Referenz({ fileId }: { fileId: string }) {
  const quelle = useBildQuelle(fileId, BUCKET_REFERENZEN);
  return (
    <View style={s.refRahmen}>
      {quelle ? <Image source={quelle} style={s.bild} contentFit="cover" /> : null}
    </View>
  );
}

const s = StyleSheet.create({
  safe: { flex: 1, backgroundColor: colors.bg },
  body: { padding: space.xl, gap: space.xl, paddingBottom: space.xxl },
  titel: { ...text.title, color: colors.txt },
  unter: { ...text.label, color: colors.mut, marginTop: -space.lg },

  hinweisBox: {
    flexDirection: 'row', gap: space.md, alignItems: 'flex-start',
    backgroundColor: 'rgba(251,191,36,0.10)',
    borderColor: colors.gold, borderWidth: StyleSheet.hairlineWidth,
    borderRadius: radius.md, padding: space.lg,
  },
  hinweisText: { ...text.label, color: colors.mut, lineHeight: 19, flex: 1 },
  mono: { ...text.mono, color: colors.txt },

  abschnitt: { gap: space.sm },
  abschnittTitel: { ...text.heading, color: colors.txt },
  erklaerung: { ...text.label, color: colors.faint, lineHeight: 18 },
  mehrzeilig: { minHeight: 76, textAlignVertical: 'top' },

  gitter: { flexDirection: 'row', flexWrap: 'wrap', gap: space.md, marginTop: space.sm },
  kachel: { width: 104, gap: space.xs },
  kachelAus: { opacity: 0.4 },
  rahmen: {
    width: 104, height: 104, borderRadius: radius.md, overflow: 'hidden',
    backgroundColor: colors.surface,
    borderColor: colors.border, borderWidth: 2,
  },
  rahmenFrei: { borderColor: colors.ok },
  rahmenFehler: { borderColor: colors.accent },
  kiChip: {
    position: 'absolute', bottom: 4, left: 4,
    backgroundColor: 'rgba(0,0,0,0.6)', borderRadius: radius.pill,
    paddingHorizontal: 5, paddingVertical: 1,
  },
  kiChipText: { fontSize: 9, fontWeight: '700', color: '#fff', letterSpacing: 0.5 },
  fehlerText: { fontSize: 10, color: colors.accent, lineHeight: 13 },
  bild: { width: '100%', height: '100%' },
  bildLeer: { alignItems: 'center', justifyContent: 'center' },
  siegel: {
    position: 'absolute', top: 5, right: 5,
    width: 20, height: 20, borderRadius: 10, backgroundColor: colors.ok,
    alignItems: 'center', justifyContent: 'center',
  },
  kachelZeile: { ...text.label, color: colors.mut },
  waehlen: {
    borderRadius: radius.pill, paddingVertical: 5, alignItems: 'center',
    backgroundColor: colors.surface2, borderColor: colors.border, borderWidth: StyleSheet.hairlineWidth,
  },
  waehlenText: { fontSize: 11, fontWeight: '700', color: colors.txt },

  reihe: { gap: space.sm, paddingTop: space.sm, paddingRight: space.lg },
  refRahmen: {
    width: 64, height: 64, borderRadius: radius.sm, overflow: 'hidden',
    backgroundColor: colors.surface,
    borderColor: colors.border, borderWidth: StyleSheet.hairlineWidth,
  },
});
