/**
 * Formulario de inspección generado dinámicamente desde los `fields` de una
 * plantilla. El renderer es tolerante: deduce key/label/type de varias formas.
 *
 * API v1.1: cada campo puede traer `group` (sección de agrupación),
 * `question` (prompt corto mostrado como etiqueta principal), `help`
 * (texto de ayuda bajo el campo) y `required`.
 */
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import React, { useCallback, useEffect, useState } from 'react';
import { Alert, ScrollView, StyleSheet, Switch, Text, TouchableOpacity, View } from 'react-native';
import { Template } from '../api/types';
import { getTemplates } from '../db/repositories';
import { createInspection } from '../sync/mutations';
import { getDb } from '../db/database';
import { newUuid, nextTempId } from '../sync/uuid';
import { RootStackParamList } from '../navigation/types';
import { MediaStrip } from '../ui/MediaStrip';
import {
  Card,
  ChipSelect,
  COLORS,
  Field,
  PrimaryButton,
  SectionTitle,
} from '../ui/components';

type Props = NativeStackScreenProps<RootStackParamList, 'InspectionForm'>;

interface NormField {
  key: string;
  label: string;
  type: 'text' | 'textarea' | 'number' | 'boolean' | 'select';
  options: string[];
  group: string;
  help: string | null;
  required: boolean;
}

function normalizeField(raw: unknown, idx: number): NormField {
  const f = (raw ?? {}) as Record<string, unknown>;
  const key = String(f.key ?? f.name ?? f.id ?? `field_${idx}`);
  // `question` (v1.1) tiene prioridad como etiqueta visible.
  const label = String(f.question ?? f.label ?? f.name ?? f.key ?? key);
  let type = String(f.type ?? 'text').toLowerCase();
  if (!['text', 'textarea', 'number', 'boolean', 'select'].includes(type)) {
    if (type === 'checkbox' || type === 'bool') type = 'boolean';
    else if (type === 'dropdown') type = 'select';
    else type = 'text';
  }
  const options = Array.isArray(f.options)
    ? (f.options as unknown[]).map((o) =>
        typeof o === 'string' ? o : String((o as Record<string, unknown>)?.value ?? o),
      )
    : [];
  return {
    key,
    label,
    type: type as NormField['type'],
    options,
    group: typeof f.group === 'string' ? f.group : '',
    help: typeof f.help === 'string' && f.help ? f.help : null,
    required: f.required === true,
  };
}

/** Agrupa los campos por `group` preservando el orden de aparición. */
function groupFields(fields: NormField[]): { group: string; items: NormField[] }[] {
  const out: { group: string; items: NormField[] }[] = [];
  for (const f of fields) {
    const last = out[out.length - 1];
    if (last && last.group === f.group) last.items.push(f);
    else out.push({ group: f.group, items: [f] });
  }
  return out;
}

const RESULTS = ['pass', 'fail', 'na'] as const;

export function InspectionFormScreen({ route, navigation }: Props) {
  const { featureId, featureName, templateId: suggestedId } = route.params;

  // Paso 1: elegir plantilla (las asignadas al proyecto llegan en el bundle).
  // Paso 2: rellenar el formulario. `chosen` = false → aún en el selector.
  const [available, setAvailable] = useState<Template[]>([]);
  const [chosen, setChosen] = useState(false);
  const [template, setTemplate] = useState<Template | null>(null);
  const [values, setValues] = useState<Record<string, unknown>>({});
  const [result, setResult] = useState<(typeof RESULTS)[number] | undefined>();
  const [notes, setNotes] = useState('');
  const [saving, setSaving] = useState(false);

  // We need the tempId and uuid for the inspection to associate photos with it before saving
  const [inspectionTempId, setInspectionTempId] = useState<number | null>(null);
  const [inspectionUuid, setInspectionUuid] = useState<string | null>(null);

  useEffect(() => {
    void getTemplates().then((all) => {
      // La plantilla sugerida (la de la feature) primero.
      all.sort((a, b) =>
        Number(b.id === suggestedId) - Number(a.id === suggestedId) ||
        a.name.localeCompare(b.name),
      );
      setAvailable(all);
    });
  }, [suggestedId]);

  const pickTemplate = useCallback((t: Template | null) => {
    setTemplate(t);
    setValues({});
    setChosen(true);
    // Generate IDs early so photos can be associated
    setInspectionTempId(nextTempId());
    setInspectionUuid(newUuid());
  }, []);

  const backToPicker = useCallback(() => {
    setChosen(false);
    setTemplate(null);
    setValues({});
    setInspectionTempId(null);
    setInspectionUuid(null);
  }, []);

  const fields: NormField[] = (template?.fields ?? []).map(normalizeField);

  const setValue = useCallback((key: string, v: unknown) => {
    setValues((prev) => ({ ...prev, [key]: v }));
  }, []);

  const onSubmit = useCallback(async () => {
    // Validación de campos obligatorios (los boolean cuentan siempre).
    const missing = fields.filter(
      (f) =>
        f.required &&
        f.type !== 'boolean' &&
        (values[f.key] == null || String(values[f.key]).trim() === ''),
    );
    if (missing.length) {
      Alert.alert(
        'Campos obligatorios',
        `Completa: ${missing.map((f) => f.label).join(', ')}`,
      );
      return;
    }
    setSaving(true);
    try {
      // Create the inspection using the pre-generated IDs
      await createInspection({
        feature_id: featureId,
        template_id: template?.id ?? undefined,
        data: values,
        result,
        notes: notes.trim() || undefined,
        status: 'completed',
        uuid: inspectionUuid ?? undefined,
        localId: inspectionTempId ?? undefined,
      });
      navigation.goBack();
    } finally {
      setSaving(false);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [featureId, values, result, notes, navigation, template, inspectionUuid, inspectionTempId]);

  const renderField = (f: NormField) => {
    const label = f.required ? `${f.label} *` : f.label;
    let control: React.ReactNode;
    if (f.type === 'boolean') {
      control = (
        <View style={styles.switchRow}>
          <Text style={styles.switchLabel}>{label}</Text>
          <Switch value={!!values[f.key]} onValueChange={(v) => setValue(f.key, v)} />
        </View>
      );
    } else if (f.type === 'select' && f.options.length) {
      control = (
        <ChipSelect
          label={label}
          value={values[f.key] as string | undefined}
          options={f.options}
          onChange={(v) => setValue(f.key, v)}
        />
      );
    } else {
      control = (
        <Field
          label={label}
          value={values[f.key] != null ? String(values[f.key]) : ''}
          onChangeText={(t) => setValue(f.key, f.type === 'number' ? Number(t) : t)}
          keyboardType={f.type === 'number' ? 'numeric' : 'default'}
          multiline={f.type === 'textarea'}
        />
      );
    }
    return (
      <View key={f.key}>
        {control}
        {f.help ? <Text style={styles.help}>{f.help}</Text> : null}
      </View>
    );
  };

  // ── Paso 1: selector de plantilla ──
  if (!chosen) {
    return (
      <ScrollView contentContainerStyle={styles.body}>
        <Text style={styles.subtitle}>{featureName}</Text>
        <Text style={styles.tplName}>Elige una plantilla</Text>

        {available.length === 0 && (
          <Text style={styles.noTemplates}>
            No hay plantillas asignadas a este proyecto. Sincroniza o crea una
            inspección libre.
          </Text>
        )}

        {available.map((t) => (
          <TouchableOpacity key={t.id} style={styles.tplCard} onPress={() => pickTemplate(t)}>
            <View style={{ flex: 1 }}>
              <Text style={styles.tplCardName}>
                {t.name}
                {t.id === suggestedId ? '  ★' : ''}
              </Text>
              {t.description ? (
                <Text style={styles.tplCardDesc} numberOfLines={2}>
                  {t.description}
                </Text>
              ) : null}
              <Text style={styles.tplCardMeta}>
                {(t.fields ?? []).length} campos
                {t.id === suggestedId ? ' · sugerida para esta feature' : ''}
              </Text>
            </View>
            <Text style={styles.tplChevron}>›</Text>
          </TouchableOpacity>
        ))}
      </ScrollView>
    );
  }

  // ── Paso 2: formulario ──
  return (
    <ScrollView contentContainerStyle={styles.body}>
      <Text style={styles.subtitle}>{featureName}</Text>
      <Text style={styles.tplName}>{template?.name ?? 'Inspección libre'}</Text>
      <TouchableOpacity onPress={backToPicker}>
        <Text style={styles.changeTpl}>‹ Cambiar plantilla</Text>
      </TouchableOpacity>

      {groupFields(fields).map((section, si) => (
        <View key={`g${si}`}>
          {section.group ? <SectionTitle>{section.group}</SectionTitle> : null}
          {section.items.map(renderField)}
        </View>
      ))}

      <SectionTitle>Resultado</SectionTitle>
      <Card style={{ marginBottom: 12 }}>
        <ChipSelect label="" value={result} options={RESULTS} onChange={setResult} />
        <Field
          label="Notas"
          value={notes}
          onChangeText={setNotes}
          placeholder="Observaciones…"
          multiline
        />
      </Card>

      {inspectionTempId && (
        <View style={{ marginBottom: 12 }}>
          <SectionTitle>Fotos de la inspección</SectionTitle>
          <MediaStrip
            parentEntity="inspection"
            parentId={inspectionTempId}
            canUpload={true}
          />
        </View>
      )}

      <PrimaryButton title="Guardar inspección" onPress={() => void onSubmit()} loading={saving} />
      <View style={{ height: 8 }} />
      <PrimaryButton title="Cancelar" variant="ghost" onPress={() => navigation.goBack()} />
    </ScrollView>
  );
}

const styles = StyleSheet.create({
  body: { padding: 16 },
  subtitle: { color: COLORS.muted, fontSize: 13 },
  tplName: { fontSize: 18, fontWeight: '700', marginBottom: 12 },
  switchRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    paddingVertical: 10,
  },
  switchLabel: { fontSize: 15, flex: 1 },
  help: { fontSize: 12, color: COLORS.muted, marginTop: -6, marginBottom: 8 },
  changeTpl: { color: COLORS.primary, fontSize: 13, fontWeight: '600', marginBottom: 12 },
  noTemplates: { color: COLORS.muted, fontSize: 14, marginVertical: 16, textAlign: 'center' },
  tplCard: {
    flexDirection: 'row',
    alignItems: 'center',
    borderWidth: 1,
    borderColor: COLORS.border,
    borderRadius: 10,
    padding: 14,
    marginBottom: 8,
    backgroundColor: '#fff',
  },
  tplCardName: { fontSize: 15, fontWeight: '700' },
  tplCardDesc: { fontSize: 13, color: COLORS.muted, marginTop: 2 },
  tplCardMeta: { fontSize: 11, color: COLORS.muted, marginTop: 4 },
  tplChevron: { fontSize: 24, color: COLORS.muted, marginLeft: 8 },
});