import * as FileSystem from 'expo-file-system';
import { router } from 'expo-router';
import { useRef, useState } from 'react';
import { Pressable, ScrollView, Text, TextInput, View } from 'react-native';
import {
  RecordingPresets,
  requestRecordingPermissionsAsync,
  setAudioModeAsync,
  useAudioRecorder,
} from 'expo-audio';
import { SafeAreaView } from 'react-native-safe-area-context';
import type { AssistantAnswer, AssistantExcerpt } from '@siop/shared';
import { useAskAssistant } from '@/api/assistant';
import { useTranscription } from '@/api/exploitation';
import { BoutonTel, EnteteFiche } from '@/composants/ui';
import { useTokens, type Tokens } from '@/theme/tokens';

/** Assistant — maquette « Assistant mobile » (validée 02/08) : même contenu
 *  et mêmes règles que le web (D2 « sourcé ou silencieux », ADR-004 §4 —
 *  le service IA n'est jamais appelé directement, toujours via l'API).
 *  D5 : la question peut être tapée OU dictée — même pipeline que la
 *  dictée déjà livrée en clôture (ADR-004 §5), la transcription REMPLIT le
 *  champ (éditable), aucun envoi automatique. */

interface Echange {
  question: string;
  reponse?: AssistantAnswer;
  erreur?: string;
}

export default function PageAssistant() {
  const t = useTokens();
  const ask = useAskAssistant();
  const transcrire = useTranscription();
  const recorder = useAudioRecorder(RecordingPresets.HIGH_QUALITY);
  const [question, setQuestion] = useState('');
  const [echanges, setEchanges] = useState<Echange[]>([]);
  const [enregistrement, setEnregistrement] = useState(false);
  const saisieRef = useRef<TextInput>(null);

  const demarrerDictee = async () => {
    const { granted } = await requestRecordingPermissionsAsync();
    if (!granted) return;
    // iOS refuse recorder.record() sans autorisation explicite de la session
    // audio (RecordingDisabledException) — même correctif qu'en clôture.
    await setAudioModeAsync({ allowsRecording: true, playsInSilentMode: true });
    await recorder.prepareToRecordAsync();
    recorder.record();
    setEnregistrement(true);
  };

  const terminerDictee = async () => {
    await recorder.stop();
    await setAudioModeAsync({ allowsRecording: false });
    setEnregistrement(false);
    const uri = recorder.uri;
    if (!uri) return;
    transcrire.mutate(
      { uri, nom: 'question.m4a', mime: 'audio/m4a' },
      {
        onSuccess: (resultat) => setQuestion(resultat.text),
        // Loi 09-08 (D5) : l'audio ne survit jamais à l'appel, succès ou pas.
        onSettled: () => void FileSystem.deleteAsync(uri, { idempotent: true }),
      },
    );
  };

  const envoyer = () => {
    const q = question.trim();
    if (q.length < 3 || ask.isPending) return;
    setQuestion('');
    setEchanges((liste) => [...liste, { question: q }]);
    ask.mutate(
      { question: q },
      {
        onSuccess: (reponse) =>
          setEchanges((liste) =>
            liste.map((e, i) => (i === liste.length - 1 ? { ...e, reponse } : e)),
          ),
        onError: (erreur) =>
          setEchanges((liste) =>
            liste.map((e, i) => (i === liste.length - 1 ? { ...e, erreur: erreur.message } : e)),
          ),
      },
    );
  };

  return (
    <SafeAreaView style={{ flex: 1, backgroundColor: t.fond }} edges={['top']}>
      <View style={{ flex: 1, padding: 14, gap: 10 }}>
        <EnteteFiche titre="Assistant" />
        <ScrollView contentContainerStyle={{ gap: 10, paddingBottom: 8, flexGrow: 1 }}>
          {echanges.length === 0 ? (
            <Text style={{ color: t.encre2, fontFamily: 'Manrope_400Regular', fontSize: 12.5 }}>
              Posez une question sur vos notices, vos historiques d'intervention ou vos
              procédures — chaque réponse cite ses sources. Quand le corpus ne porte pas la
              réponse, l'assistant le dit au lieu d'inventer.
            </Text>
          ) : null}
          {echanges.map((e, i) => (
            <View key={i} style={{ gap: 8 }}>
              <Text
                style={{
                  alignSelf: 'flex-end',
                  backgroundColor: t.primaire,
                  color: '#fff',
                  borderRadius: 13,
                  borderBottomRightRadius: 3,
                  paddingHorizontal: 12,
                  paddingVertical: 9,
                  maxWidth: '85%',
                  fontFamily: 'Manrope_600SemiBold',
                  fontSize: 12.5,
                }}
              >
                {e.question}
              </Text>
              {e.reponse ? (
                <Reponse reponse={e.reponse} t={t} surReformuler={() => saisieRef.current?.focus()} />
              ) : e.erreur ? (
                <Text style={{ color: t.danger, fontFamily: 'Manrope_600SemiBold', fontSize: 12.5 }}>
                  {e.erreur}
                </Text>
              ) : (
                <Text style={{ color: t.encre3, fontFamily: 'Manrope_400Regular', fontSize: 12.5 }}>
                  Recherche dans le corpus…
                </Text>
              )}
            </View>
          ))}
        </ScrollView>

        {enregistrement ? (
          <View
            style={{
              alignItems: 'center',
              gap: 8,
              borderWidth: 1.5,
              borderColor: t.bordure,
              borderRadius: 13,
              backgroundColor: t.surface,
              padding: 16,
            }}
          >
            <View
              style={{
                width: 44,
                height: 44,
                borderRadius: 22,
                backgroundColor: t.prioBloque,
                alignItems: 'center',
                justifyContent: 'center',
              }}
            >
              <Text style={{ fontSize: 18 }}>🎙</Text>
            </View>
            <Text style={{ color: t.encre2, fontFamily: 'Manrope_400Regular', fontSize: 11.5 }}>
              Enregistrement en cours…
            </Text>
            <BoutonTel
              libelle="■ Terminer la dictée"
              surAppui={() => void terminerDictee()}
            />
          </View>
        ) : (
          <View
            style={{
              flexDirection: 'row',
              alignItems: 'center',
              gap: 8,
              borderWidth: 1.5,
              borderColor: t.bordureForte,
              borderRadius: 10,
              backgroundColor: t.surface,
              paddingHorizontal: 10,
              paddingVertical: 6,
            }}
          >
            <Pressable
              accessibilityRole="button"
              accessibilityLabel="Dicter la question"
              disabled={transcrire.isPending}
              onPress={() => void demarrerDictee()}
              style={{
                width: 26,
                height: 26,
                borderRadius: 13,
                backgroundColor: t.primaireDoux,
                alignItems: 'center',
                justifyContent: 'center',
              }}
            >
              <Text style={{ fontSize: 13 }}>🎙</Text>
            </Pressable>
            <TextInput
              ref={saisieRef}
              accessibilityLabel="Poser une question"
              value={transcrire.isPending ? 'Transcription…' : question}
              editable={!transcrire.isPending}
              onChangeText={setQuestion}
              onSubmitEditing={envoyer}
              maxLength={500}
              placeholder="Poser une question…"
              placeholderTextColor={t.encre3}
              style={{ flex: 1, color: t.encre, fontFamily: 'Manrope_600SemiBold', fontSize: 13 }}
            />
            <Pressable
              accessibilityRole="button"
              accessibilityLabel="Envoyer"
              disabled={question.trim().length < 3 || ask.isPending}
              onPress={envoyer}
            >
              <Text
                style={{
                  color: question.trim().length < 3 || ask.isPending ? t.encre3 : t.primaire,
                  fontFamily: 'Manrope_800ExtraBold',
                  fontSize: 12.5,
                }}
              >
                Envoyer
              </Text>
            </Pressable>
          </View>
        )}
        {transcrire.isError ? (
          <Text style={{ color: t.danger, fontFamily: 'Manrope_600SemiBold', fontSize: 11.5 }}>
            {transcrire.error.message}
          </Text>
        ) : null}
      </View>
    </SafeAreaView>
  );
}

function Reponse({
  reponse,
  t,
  surReformuler,
}: {
  reponse: AssistantAnswer;
  t: Tokens;
  surReformuler: () => void;
}) {
  if (reponse.mode === 'REFUSAL') {
    return (
      <View
        style={{
          borderWidth: 1.5,
          borderColor: t.bordureForte,
          borderStyle: 'dashed',
          borderRadius: 13,
          padding: 12,
          gap: 8,
          backgroundColor: t.surface,
        }}
      >
        <Text style={{ fontFamily: 'Manrope_800ExtraBold', fontSize: 12.5, color: t.encre }}>
          Je ne trouve pas de source fiable dans votre bibliothèque — je préfère ne pas inventer.
        </Text>
        <Text style={{ fontFamily: 'Manrope_400Regular', fontSize: 11.5, color: t.encre2 }}>
          J'ai cherché dans {reponse.corpus.documents} document
          {reponse.corpus.documents > 1 ? 's' : ''} indexé
          {reponse.corpus.documents > 1 ? 's' : ''} et {reponse.corpus.reports} bilan
          {reponse.corpus.reports > 1 ? 's' : ''} d'intervention : rien d'assez proche de votre
          question.
        </Text>
        <BoutonTel libelle="Reformuler ma question" variante="contour" surAppui={surReformuler} />
      </View>
    );
  }
  return (
    <View
      style={{
        backgroundColor: t.surface,
        borderColor: t.bordure,
        borderWidth: 1,
        borderRadius: 13,
        borderBottomLeftRadius: 3,
        padding: 11,
        gap: 9,
      }}
    >
      {reponse.mode === 'GENERATED' && reponse.answer ? (
        <Text style={{ fontFamily: 'Manrope_500Medium', fontSize: 12.5, color: t.encre }}>
          {reponse.answer}
        </Text>
      ) : (
        <Text style={{ fontFamily: 'Manrope_500Medium', fontSize: 12.5, color: t.encre }}>
          Voici ce que portent vos sources — les extraits sont cités tels quels.
        </Text>
      )}
      <View
        style={{ gap: 7, borderTopWidth: 1, borderTopColor: t.bordure, paddingTop: 9 }}
      >
        {reponse.excerpts.map((ex, i) => (
          <Source key={`${ex.locator}-${i}`} ex={ex} no={i + 1} t={t} />
        ))}
      </View>
      <View
        style={{
          flexDirection: 'row',
          gap: 6,
          backgroundColor: t.safranDoux,
          borderRadius: 9,
          padding: 8,
        }}
      >
        <Text style={{ color: t.alerte, fontSize: 10.5, fontFamily: 'Manrope_600SemiBold', flex: 1 }}>
          ⚠ L'IA propose, vous validez : vérifiez la notice avant d'agir sur l'appareil.
        </Text>
      </View>
    </View>
  );
}

function Source({ ex, no, t }: { ex: AssistantExcerpt; no: number; t: Tokens }) {
  const ouvrir = () => {
    if (ex.sourceType === 'DOCUMENT' && ex.documentId) router.push(`/bibliotheque/${ex.documentId}`);
    else if (ex.workOrderId) router.push(`/ot/${ex.workOrderId}`);
  };
  return (
    <Pressable
      accessibilityRole="button"
      onPress={ouvrir}
      style={{ backgroundColor: t.surface2, borderRadius: 9, padding: 9, gap: 3 }}
    >
      <View style={{ flexDirection: 'row', alignItems: 'center', gap: 7 }}>
        <Text
          style={{
            width: 16,
            height: 16,
            borderRadius: 5,
            backgroundColor: t.primaireDoux,
            color: t.primaire,
            fontSize: 10,
            fontFamily: 'Manrope_800ExtraBold',
            textAlign: 'center',
            lineHeight: 16,
          }}
        >
          {no}
        </Text>
        <Text
          numberOfLines={1}
          style={{ flex: 1, fontFamily: 'Manrope_700Bold', fontSize: 11.5, color: t.encre }}
        >
          {ex.title}
        </Text>
      </View>
      <Text style={{ fontFamily: 'Manrope_400Regular', fontSize: 10.5, color: t.encre2, marginLeft: 23 }}>
        {ex.sourceType === 'DOCUMENT' ? 'Bibliothèque' : 'Historique'} · {ex.locator}
      </Text>
      <Text
        style={{
          fontFamily: 'Manrope_500Medium',
          fontStyle: 'italic',
          fontSize: 11,
          color: t.encre2,
          marginLeft: 23,
          borderLeftWidth: 2,
          borderLeftColor: t.safran,
          paddingLeft: 7,
        }}
      >
        « {ex.content} »
      </Text>
      <Text style={{ marginLeft: 23, color: t.primaire, fontFamily: 'Manrope_700Bold', fontSize: 11 }}>
        {ex.sourceType === 'DOCUMENT' ? 'Voir le document' : "Ouvrir l'OT"}
      </Text>
    </Pressable>
  );
}
