import React, { useEffect, useState } from "react";
import { ActivityIndicator, Modal, Pressable, ScrollView, Switch, Text, TextInput, View } from "react-native";
import { useQuery } from "@tanstack/react-query";
import { KeyboardAwareScrollView } from "react-native-keyboard-controller";
import Ionicons from "@react-native-vector-icons/ionicons";

import { ADMIN_TOKEN, api } from "@/src/api";
import { Field, Section } from "@/src/admin/schemas";
import { queryClient } from "@/src/query-client";
import { makeStyles, useTheme } from "@/src/theme";
import { radius, space } from "@/src/ui";

const adminApi = <T,>(path: string, method = "GET", body?: unknown) => api<T>(path, { method, body, tokenKey: ADMIN_TOKEN });

function toForm(fields: Field[], item: any) {
  const f: Record<string, any> = {};
  fields.forEach((fd) => {
    const v = item?.[fd.key];
    if (fd.type === "json") f[fd.key] = v !== undefined ? JSON.stringify(v, null, 2) : "";
    else if (fd.type === "bool") f[fd.key] = v ?? true;
    else if (fd.type === "categories") f[fd.key] = v ?? [];
    else if (fd.type === "password") f[fd.key] = "";
    else f[fd.key] = v ?? (fd.type === "select" ? fd.options![0] : "");
  });
  return f;
}

function fromForm(fields: Field[], form: Record<string, any>) {
  const out: Record<string, any> = {};
  for (const fd of fields) {
    const v = form[fd.key];
    if (fd.type === "number") out[fd.key] = v === "" ? null : Number(v);
    else if (fd.type === "json") {
      if (v.trim()) out[fd.key] = JSON.parse(v);
    } else if (fd.type === "password") {
      if (v) out[fd.key] = v;
    } else out[fd.key] = v;
  }
  return out;
}

export function AdminForm({ fields, initial, onSubmit, onCancel, testPrefix }: { fields: Field[]; initial: any; onSubmit: (d: any) => Promise<void>; onCancel?: () => void; testPrefix: string }) {
  const styles = useStyles();
  const { colors } = useTheme();
  const [form, setForm] = useState(() => toForm(fields, initial));
  const [saving, setSaving] = useState(false);
  const [msg, setMsg] = useState<{ ok: boolean; text: string } | null>(null);
  const cats = useQuery({ queryKey: ["admin", "categories"], queryFn: () => adminApi<any[]>("/admin/categories"), enabled: fields.some((f) => f.type === "categories") });
  useEffect(() => setForm(toForm(fields, initial)), [fields, initial]);
  const set = (k: string, v: any) => setForm((f) => ({ ...f, [k]: v }));

  const save = async () => {
    setSaving(true);
    setMsg(null);
    try {
      await onSubmit(fromForm(fields, form));
      setMsg({ ok: true, text: "Salvo com sucesso" });
    } catch (e: any) {
      setMsg({ ok: false, text: e instanceof SyntaxError ? "JSON inválido" : e.message });
    } finally {
      setSaving(false);
    }
  };

  return (
    <View>
      {fields.map((fd) => (
        <View key={fd.key} style={{ marginBottom: space.md }}>
          <Text style={styles.label}>{fd.label}</Text>
          {fd.type === "bool" ? (
            <Switch testID={`${testPrefix}-field-${fd.key}`} value={!!form[fd.key]} onValueChange={(v) => set(fd.key, v)} trackColor={{ true: colors.brandPrimary, false: colors.border }} />
          ) : fd.type === "select" ? (
            <View style={styles.row}>
              {fd.options!.map((o) => (
                <Pressable key={o} testID={`${testPrefix}-field-${fd.key}-${o}`} onPress={() => set(fd.key, o)} style={[styles.opt, form[fd.key] === o && styles.optActive]}>
                  <Text style={styles.optText}>{o}</Text>
                </Pressable>
              ))}
            </View>
          ) : fd.type === "categories" ? (
            <View style={[styles.row, { flexWrap: "wrap" }]}>
              {(cats.data ?? []).map((c) => {
                const sel = form[fd.key].includes(c.id);
                return (
                  <Pressable key={c.id} testID={`${testPrefix}-cat-${c.id}`} onPress={() => set(fd.key, sel ? form[fd.key].filter((x: string) => x !== c.id) : [...form[fd.key], c.id])} style={[styles.opt, sel && styles.optActive]}>
                    <Text style={styles.optText}>{c.name}</Text>
                  </Pressable>
                );
              })}
            </View>
          ) : (
            <TextInput
              testID={`${testPrefix}-field-${fd.key}`}
              value={String(form[fd.key] ?? "")}
              onChangeText={(v) => set(fd.key, v)}
              multiline={fd.type === "multiline" || fd.type === "json"}
              secureTextEntry={fd.type === "password"}
              keyboardType={fd.type === "number" ? "numeric" : "default"}
              autoCapitalize="none"
              placeholder={fd.hint}
              placeholderTextColor={colors.muted}
              style={[styles.input, (fd.type === "multiline" || fd.type === "json") && styles.multi, (fd.type === "json" || fd.key === "config") && styles.mono]}
            />
          )}
        </View>
      ))}
      {msg && <Text testID={`${testPrefix}-message`} style={{ color: msg.ok ? colors.success : colors.error, marginBottom: space.sm }}>{msg.text}</Text>}
      <View style={styles.row}>
        <Pressable testID={`${testPrefix}-save`} onPress={save} style={styles.primary} disabled={saving}>
          {saving ? <ActivityIndicator color={colors.onBrandPrimary} /> : <Text style={styles.primaryText}>Salvar</Text>}
        </Pressable>
        {onCancel && (
          <Pressable testID={`${testPrefix}-cancel`} onPress={onCancel} style={styles.secondary}>
            <Text style={styles.optText}>Fechar</Text>
          </Pressable>
        )}
      </View>
    </View>
  );
}

export function AdminCrud({ section }: { section: Section }) {
  const styles = useStyles();
  const { colors } = useTheme();
  const q = useQuery({ queryKey: ["admin", section.key], queryFn: () => adminApi<any[]>(`/admin/${section.key}`) });
  const [editing, setEditing] = useState<any | null>(null);
  const [confirmDel, setConfirmDel] = useState<string | null>(null);

  const submit = async (data: any) => {
    if (editing?.id) await adminApi(`/admin/${section.key}/${editing.id}`, "PUT", data);
    else await adminApi(`/admin/${section.key}`, "POST", data);
    await q.refetch();
    queryClient.invalidateQueries({ queryKey: ["admin", "stats"] });
    setEditing(null);
  };

  return (
    <View testID={`admin-section-${section.key}`}>
      <View style={[styles.row, { justifyContent: "space-between", marginBottom: space.lg }]}>
        <Text style={styles.h2}>{section.label}</Text>
        <Pressable testID={`admin-${section.key}-add`} onPress={() => setEditing({})} style={styles.primary}>
          <Text style={styles.primaryText}>+ Adicionar</Text>
        </Pressable>
      </View>
      {q.isLoading && <ActivityIndicator color={colors.brandPrimary} />}
      {q.error && <Text style={{ color: colors.error }}>{(q.error as Error).message}</Text>}
      {(q.data ?? []).map((it) => (
        <View key={it.id} style={styles.item} testID={`admin-${section.key}-item-${it.id}`}>
          <View style={{ flex: 1 }}>
            <Text style={styles.itemTitle}>{String(it[section.titleKey] ?? "—")}</Text>
            {section.subKey && <Text style={styles.itemSub} numberOfLines={1}>{String(it[section.subKey] ?? "")} {it.active === false ? "· inativo" : ""}</Text>}
            <Text style={styles.itemId} selectable>ID: {it.id}</Text>
          </View>
          <Pressable testID={`admin-${section.key}-edit-${it.id}`} onPress={() => setEditing(it)} style={styles.iconBtn}>
            <Ionicons name="create-outline" size={20} color={colors.onSurface} />
          </Pressable>
          {confirmDel === it.id ? (
            <Pressable
              testID={`admin-${section.key}-confirm-delete-${it.id}`}
              onPress={async () => {
                await adminApi(`/admin/${section.key}/${it.id}`, "DELETE").catch(() => {});
                setConfirmDel(null);
                q.refetch();
                queryClient.invalidateQueries({ queryKey: ["admin", "stats"] });
              }}
              style={[styles.iconBtn, { backgroundColor: colors.error, width: 90 }]}
            >
              <Text style={{ color: colors.onError, fontWeight: "700" }}>Confirmar</Text>
            </Pressable>
          ) : (
            <Pressable testID={`admin-${section.key}-delete-${it.id}`} onPress={() => setConfirmDel(it.id)} style={styles.iconBtn}>
              <Ionicons name="trash-outline" size={20} color={colors.error} />
            </Pressable>
          )}
        </View>
      ))}
      <Modal visible={!!editing} transparent animationType="fade" onRequestClose={() => setEditing(null)}>
        <View style={styles.backdrop}>
          <View style={styles.modal}>
            <Text style={styles.h2}>{editing?.id ? "Editar" : "Novo"} — {section.label}</Text>
            <KeyboardAwareScrollView bottomOffset={24} style={{ marginTop: space.lg }}>
              {editing && <AdminForm testPrefix={`admin-${section.key}-form`} fields={section.fields} initial={editing} onSubmit={submit} onCancel={() => setEditing(null)} />}
            </KeyboardAwareScrollView>
          </View>
        </View>
      </Modal>
    </View>
  );
}

export const AdminScroll = ScrollView;

const useStyles = makeStyles((c) => ({
  label: { color: c.onSurfaceSecondary, fontSize: 13, fontWeight: "600", marginBottom: space.xs },
  input: { backgroundColor: c.surfaceTertiary, color: c.onSurface, borderRadius: radius.sm, borderWidth: 1, borderColor: c.border, paddingHorizontal: space.md, minHeight: 44, fontSize: 14 },
  multi: { minHeight: 120, textAlignVertical: "top", paddingTop: space.sm },
  mono: { fontFamily: "monospace" },
  row: { flexDirection: "row", alignItems: "center", gap: space.sm },
  opt: { paddingHorizontal: space.md, height: 36, justifyContent: "center", borderRadius: radius.pill, backgroundColor: c.surfaceTertiary, borderWidth: 1, borderColor: c.border },
  optActive: { backgroundColor: c.brandPrimary, borderColor: c.brandPrimary },
  optText: { color: c.onSurface, fontWeight: "600", fontSize: 13 },
  primary: { backgroundColor: c.brandPrimary, height: 44, paddingHorizontal: space.xl, borderRadius: radius.sm, alignItems: "center", justifyContent: "center" },
  primaryText: { color: c.onBrandPrimary, fontWeight: "800" },
  secondary: { backgroundColor: c.surfaceTertiary, height: 44, paddingHorizontal: space.xl, borderRadius: radius.sm, alignItems: "center", justifyContent: "center" },
  h2: { color: c.onSurface, fontSize: 22, fontWeight: "800" },
  item: { flexDirection: "row", alignItems: "center", gap: space.sm, backgroundColor: c.surfaceSecondary, borderRadius: radius.md, padding: space.md, marginBottom: space.sm, borderWidth: 1, borderColor: c.border },
  itemTitle: { color: c.onSurface, fontSize: 15, fontWeight: "700" },
  itemSub: { color: c.muted, fontSize: 12, marginTop: 2 },
  itemId: { color: c.muted, fontSize: 10, marginTop: 2 },
  iconBtn: { width: 44, height: 44, borderRadius: radius.sm, alignItems: "center", justifyContent: "center", backgroundColor: c.surfaceTertiary },
  backdrop: { flex: 1, backgroundColor: c.overlay, alignItems: "center", justifyContent: "center", padding: space.lg },
  modal: { width: "100%", maxWidth: 640, maxHeight: "90%", backgroundColor: c.surfaceSecondary, borderRadius: radius.lg, padding: space.xl, borderWidth: 1, borderColor: c.border },
}));
