/**
 * OAuth-Browser — Verwaltung der OAuth-Provider (Spotify + Custom) und ihrer
 * Credentials. Eingesetzt von SettingsScreen → Sektion "OAuth-Apps".
 *
 * Pro Service:
 *  - Status (verbunden / konfiguriert / leer)
 *  - client_id + client_secret (Passwort-Toggle)
 *  - Bei Custom-Services: auch auth_url + token_url + scopes editierbar
 *  - "Autorisieren ↗" oeffnet die Provider-Auth-Seite im System-Browser
 *  - "Abmelden" + (bei Custom) "🗑 Service entfernen"
 *
 * Plus: "+ Custom-Service" oeffnet ein Modal fuer name/auth_url/token_url/scopes.
 *
 * Hinweis zu Credentials: client_id/client_secret laufen ueber HTTP zur
 * Bridge, von dort zum Brain. Wenn die App via RVS verbunden ist, geht alles
 * ueber TLS (wss://) — der Wert ist nie im Klartext im Netz unterwegs.
 */

import React, { useCallback, useEffect, useState } from 'react';
import {
  ActivityIndicator,
  Alert,
  FlatList,
  Linking,
  Modal,
  ScrollView,
  StyleSheet,
  Text,
  TextInput,
  TouchableOpacity,
  View,
} from 'react-native';

import brainApi, { OAuthServiceStatus, OAuthAppConfig } from '../services/brainApi';

const COL_OK = '#34C759';
const COL_PENDING = '#FFD60A';
const COL_OFF = '#666680';
const COL_ERR = '#FF6B6B';

function fmtExpiry(secs: number | null | undefined): string {
  if (secs == null) return '';
  if (secs <= 0) return 'abgelaufen';
  if (secs < 60) return `${secs}s`;
  if (secs < 3600) return `${Math.round(secs / 60)} min`;
  if (secs < 86400) return `${Math.round(secs / 3600)} h`;
  return `${Math.round(secs / 86400)} Tage`;
}

interface MergedService extends OAuthServiceStatus {
  app?: OAuthAppConfig;
  isDefault: boolean;
}

export const OAuthBrowser: React.FC = () => {
  const [services, setServices] = useState<MergedService[]>([]);
  const [loading, setLoading] = useState(false);
  const [err, setErr] = useState<string | null>(null);
  const [editService, setEditService] = useState<MergedService | null>(null);
  const [showNew, setShowNew] = useState(false);

  const load = useCallback(() => {
    setLoading(true); setErr(null);
    Promise.all([brainApi.listOAuthServices(), brainApi.getOAuthApps()])
      .then(([statusRes, appsRes]) => {
        const apps = appsRes.apps || {};
        const defaults = new Set(appsRes.defaults || []);
        const items: MergedService[] = (statusRes.services || []).map(s => ({
          ...s,
          app: apps[s.service],
          isDefault: defaults.has(s.service),
        }));
        items.sort((a, b) => {
          if (a.authenticated !== b.authenticated) return a.authenticated ? -1 : 1;
          if (a.configured !== b.configured) return a.configured ? -1 : 1;
          return a.service.localeCompare(b.service);
        });
        setServices(items);
      })
      .catch(e => setErr(String(e?.message || e)))
      .finally(() => setLoading(false));
  }, []);

  useEffect(() => { load(); }, [load]);

  const renderItem = ({ item }: { item: MergedService }) => {
    let statusColor: string = COL_OFF;
    let statusIcon = '⚫';
    let statusText = 'nicht konfiguriert';
    if (item.authenticated) {
      statusColor = COL_OK; statusIcon = '✅';
      statusText = `verbunden${item.expiresInSec != null ? ' · noch ' + fmtExpiry(item.expiresInSec) : ''}`;
    } else if (item.configured) {
      statusColor = COL_PENDING; statusIcon = '🟡';
      statusText = 'konfiguriert, nicht autorisiert';
    }
    return (
      <TouchableOpacity style={s.row} onPress={() => setEditService(item)}>
        <View style={{flex: 1, marginRight: 8}}>
          <View style={{flexDirection: 'row', alignItems: 'center', gap: 6, marginBottom: 2}}>
            <Text style={{color: '#E0E0F0', fontWeight: '600', fontSize: 14, textTransform: 'capitalize'}}>{item.service}</Text>
            {!item.isDefault ? (
              <Text style={{color: '#8888AA', fontSize: 10}}>(custom)</Text>
            ) : null}
          </View>
          <Text style={{color: statusColor, fontSize: 12}}>{statusIcon}  {statusText}</Text>
        </View>
      </TouchableOpacity>
    );
  };

  return (
    <View style={{flex: 1}}>
      <View style={s.toolbar}>
        <Text style={{color: '#8888AA', fontSize: 11, flex: 1}}>
          Verbinde ARIA mit externen Services (Spotify u.a.).
        </Text>
        <TouchableOpacity onPress={load} style={s.iconBtn}>
          <Text style={{fontSize: 16}}>{'↻'}</Text>
        </TouchableOpacity>
        <TouchableOpacity onPress={() => setShowNew(true)} style={[s.iconBtn, {backgroundColor: '#0096FF'}]}>
          <Text style={{fontSize: 13, color: '#fff', fontWeight: '700'}}>+ Custom</Text>
        </TouchableOpacity>
      </View>

      {err ? <Text style={s.err}>{err}</Text> : null}

      {loading && services.length === 0 ? (
        <ActivityIndicator color="#0096FF" style={{marginTop: 20}} />
      ) : (
        <FlatList
          data={services}
          keyExtractor={s => s.service}
          renderItem={renderItem}
          nestedScrollEnabled={true}
          ListEmptyComponent={
            <Text style={{color: '#555570', textAlign: 'center', padding: 20, fontStyle: 'italic'}}>
              (keine OAuth-Services — frag ARIA: "verbinde mich mit X")
            </Text>
          }
          contentContainerStyle={{paddingBottom: 20}}
        />
      )}

      {editService ? (
        <OAuthEditModal
          service={editService}
          onClose={() => setEditService(null)}
          onReload={() => { setEditService(null); load(); }}
        />
      ) : null}

      {showNew ? (
        <OAuthCustomNewModal
          onClose={() => setShowNew(false)}
          onCreated={() => { setShowNew(false); load(); }}
        />
      ) : null}
    </View>
  );
};

// ── Edit-Modal (Credentials + Authorize + Revoke + Delete) ──────────

interface EditProps {
  service: MergedService;
  onClose: () => void;
  onReload: () => void;
}

const OAuthEditModal: React.FC<EditProps> = ({ service: svc, onClose, onReload }) => {
  const [clientId, setClientId] = useState(svc.app?.client_id || '');
  const [clientSecret, setClientSecret] = useState('');
  const [showSecret, setShowSecret] = useState(false);
  const [authUrl, setAuthUrl] = useState(svc.app?.auth_url || '');
  const [tokenUrl, setTokenUrl] = useState(svc.app?.token_url || '');
  const [scopes, setScopes] = useState((svc.app?.scopes || []).join(' '));
  const [saving, setSaving] = useState(false);
  const [showAdvanced, setShowAdvanced] = useState(false);

  const save = async () => {
    if (!clientId.trim()) {
      Alert.alert('Fehler', 'client_id darf nicht leer sein.');
      return;
    }
    setSaving(true);
    const body: any = {
      service: svc.service,
      client_id: clientId.trim(),
    };
    if (clientSecret) body.client_secret = clientSecret;
    if (authUrl.trim()) body.auth_url = authUrl.trim();
    if (tokenUrl.trim()) body.token_url = tokenUrl.trim();
    if (scopes.trim()) body.scopes = scopes.trim().split(/\s+/).filter(Boolean);
    try {
      await brainApi.saveOAuthApp(body);
      onReload();
    } catch (e: any) {
      Alert.alert('Speichern fehlgeschlagen', String(e?.message || e));
    } finally {
      setSaving(false);
    }
  };

  const authorize = async () => {
    if (!svc.configured) {
      Alert.alert('Erst Credentials eintragen', 'client_id und client_secret muessen vor dem Autorisieren gespeichert sein.');
      return;
    }
    try {
      const r = await brainApi.authorizeOAuth(svc.service);
      // Im System-Browser oeffnen — InAppBrowser wuerde z.T. von Providern blockiert
      const ok = await Linking.canOpenURL(r.url);
      if (!ok) {
        Alert.alert('Browser nicht verfuegbar', 'Konnte die Auth-URL nicht oeffnen.');
        return;
      }
      Linking.openURL(r.url);
      Alert.alert(
        'Im Browser anmelden',
        `Bitte stimme bei ${svc.service} zu. Nach dem Redirect zur Callback-Seite kannst du den Tab schliessen — ARIA bekommt das Token automatisch.\n\nDie Status-Anzeige in der App aktualisiert sich nach Refresh.`,
        [{ text: 'OK', onPress: () => setTimeout(onReload, 8000) }],
      );
    } catch (e: any) {
      Alert.alert('Authorize fehlgeschlagen', String(e?.message || e));
    }
  };

  const revoke = () => {
    Alert.alert(
      'Abmelden?',
      `Token fuer ${svc.service} entfernen. Du musst danach neu autorisieren.`,
      [
        { text: 'Abbrechen', style: 'cancel' },
        {
          text: 'Abmelden',
          style: 'destructive',
          onPress: async () => {
            try { await brainApi.revokeOAuth(svc.service); onReload(); }
            catch (e: any) { Alert.alert('Fehler', String(e?.message || e)); }
          },
        },
      ],
    );
  };

  const removeService = () => {
    Alert.alert(
      'Service komplett entfernen?',
      `"${svc.service}" wird inkl. client_id/secret und Token geloescht.`,
      [
        { text: 'Abbrechen', style: 'cancel' },
        {
          text: 'Loeschen',
          style: 'destructive',
          onPress: async () => {
            try { await brainApi.deleteOAuthApp(svc.service); onReload(); }
            catch (e: any) { Alert.alert('Fehler', String(e?.message || e)); }
          },
        },
      ],
    );
  };

  return (
    <Modal visible animationType="slide" onRequestClose={onClose} transparent={false}>
      <View style={s.modal}>
        <View style={s.modalHeader}>
          <Text style={s.modalTitle} numberOfLines={1}>{svc.service}</Text>
          <TouchableOpacity onPress={onClose} hitSlop={{top:8,bottom:8,left:8,right:8}}>
            <Text style={{color: '#8888AA', fontSize: 18}}>{'✕'}</Text>
          </TouchableOpacity>
        </View>

        <ScrollView style={{flex: 1}} contentContainerStyle={{padding: 16}}>
          {svc.authenticated ? (
            <View style={[s.metaBox, {borderLeftWidth: 3, borderLeftColor: COL_OK, marginBottom: 12}]}>
              <Text style={[s.meta, {color: COL_OK, fontWeight: '700'}]}>
                ✅ verbunden{svc.expiresInSec != null ? ` · Token noch ${fmtExpiry(svc.expiresInSec)}` : ''}
              </Text>
              {svc.hasRefresh ? <Text style={s.meta}>refresh_token vorhanden — auto-renew aktiv</Text>
                              : <Text style={[s.meta, {color: COL_ERR}]}>KEIN refresh_token — Token verfaellt komplett</Text>}
              {svc.scope ? <Text style={s.meta}>scopes: {svc.scope}</Text> : null}
            </View>
          ) : null}

          <Text style={s.label}>client_id</Text>
          <TextInput
            style={s.input}
            value={clientId}
            onChangeText={setClientId}
            placeholder="aus dem Provider-Developer-Dashboard"
            placeholderTextColor="#444460"
            autoCapitalize="none"
            autoCorrect={false}
          />

          <Text style={s.label}>
            client_secret {svc.app?.has_client_secret ? '— gespeichert (leer = behalten)' : '— fehlt'}
          </Text>
          <View style={{flexDirection: 'row', gap: 6}}>
            <TextInput
              style={[s.input, {flex: 1}]}
              value={clientSecret}
              onChangeText={setClientSecret}
              placeholder={svc.app?.has_client_secret ? '(neuen eintragen oder leer lassen)' : 'aus dem Dashboard'}
              placeholderTextColor="#444460"
              secureTextEntry={!showSecret}
              autoCapitalize="none"
              autoCorrect={false}
            />
            <TouchableOpacity
              style={[s.btn, {backgroundColor: '#1A1A2E', justifyContent: 'center'}]}
              onPress={() => setShowSecret(v => !v)}
            >
              <Text style={{color: '#8888AA', fontSize: 14}}>{showSecret ? '🙈' : '👁'}</Text>
            </TouchableOpacity>
          </View>

          {/* URLs/Scopes: bei Defaults hinter "advanced" versteckt damit Stefan
              nicht ausversehen die Spotify-URLs ueberschreibt. */}
          {svc.isDefault ? (
            <TouchableOpacity onPress={() => setShowAdvanced(v => !v)} style={{marginTop: 12}}>
              <Text style={{color: '#666680', fontSize: 11, fontStyle: 'italic'}}>
                {showAdvanced ? '▼' : '▶'} Default-URLs ueberschreiben (advanced)
              </Text>
            </TouchableOpacity>
          ) : null}

          {(!svc.isDefault || showAdvanced) ? (
            <View style={{marginTop: 8}}>
              <Text style={s.label}>auth_url</Text>
              <TextInput
                style={s.input}
                value={authUrl}
                onChangeText={setAuthUrl}
                placeholder="https://provider.com/oauth/authorize"
                placeholderTextColor="#444460"
                autoCapitalize="none"
                autoCorrect={false}
              />
              <Text style={s.label}>token_url</Text>
              <TextInput
                style={s.input}
                value={tokenUrl}
                onChangeText={setTokenUrl}
                placeholder="https://provider.com/oauth/token"
                placeholderTextColor="#444460"
                autoCapitalize="none"
                autoCorrect={false}
              />
              <Text style={s.label}>scopes (space-separated)</Text>
              <TextInput
                style={s.input}
                value={scopes}
                onChangeText={setScopes}
                placeholder="read write user.email"
                placeholderTextColor="#444460"
                autoCapitalize="none"
                autoCorrect={false}
              />
            </View>
          ) : null}

          <View style={{flexDirection: 'row', gap: 8, marginTop: 16}}>
            <TouchableOpacity
              style={[s.btn, {backgroundColor: '#0096FF', flex: 1}]}
              onPress={save}
              disabled={saving}
            >
              <Text style={{color: '#fff', textAlign: 'center', fontWeight: '700'}}>
                {saving ? 'speichert...' : 'Speichern'}
              </Text>
            </TouchableOpacity>
            <TouchableOpacity
              style={[s.btn, {backgroundColor: svc.configured ? '#34C759' : '#1E1E2E', flex: 1}]}
              onPress={authorize}
              disabled={!svc.configured}
            >
              <Text style={{color: svc.configured ? '#fff' : '#555570', textAlign: 'center', fontWeight: '700'}}>
                Autorisieren ↗
              </Text>
            </TouchableOpacity>
          </View>

          {svc.authenticated ? (
            <TouchableOpacity
              style={[s.btn, {backgroundColor: '#3A1F1F', borderColor: COL_ERR, marginTop: 12}]}
              onPress={revoke}
            >
              <Text style={{color: COL_ERR, textAlign: 'center', fontWeight: '700'}}>Abmelden (Token loeschen)</Text>
            </TouchableOpacity>
          ) : null}

          {!svc.isDefault ? (
            <TouchableOpacity
              style={[s.btn, {backgroundColor: '#3A1F1F', borderColor: COL_ERR, marginTop: 8}]}
              onPress={removeService}
            >
              <Text style={{color: COL_ERR, textAlign: 'center', fontWeight: '700'}}>🗑 Service komplett entfernen</Text>
            </TouchableOpacity>
          ) : null}

          <View style={{height: 30}} />
        </ScrollView>
      </View>
    </Modal>
  );
};

// ── Neuer Custom-Provider ──────────────────────────────────────────

interface NewProps {
  onClose: () => void;
  onCreated: () => void;
}

const OAuthCustomNewModal: React.FC<NewProps> = ({ onClose, onCreated }) => {
  const [name, setName] = useState('');
  const [authUrl, setAuthUrl] = useState('https://');
  const [tokenUrl, setTokenUrl] = useState('https://');
  const [scopes, setScopes] = useState('');
  const [creating, setCreating] = useState(false);

  const create = async () => {
    const svc = name.trim().toLowerCase();
    if (!/^[a-z0-9_-]+$/.test(svc)) {
      Alert.alert('Ungueltiger Name', 'Erlaubt: a-z 0-9 _ -');
      return;
    }
    if (!authUrl.startsWith('http') || !tokenUrl.startsWith('http')) {
      Alert.alert('Ungueltige URLs', 'auth_url und token_url muessen http(s):// sein.');
      return;
    }
    setCreating(true);
    try {
      const body: any = { service: svc, auth_url: authUrl.trim(), token_url: tokenUrl.trim() };
      if (scopes.trim()) body.scopes = scopes.trim().split(/\s+/).filter(Boolean);
      await brainApi.saveOAuthApp(body);
      onCreated();
    } catch (e: any) {
      Alert.alert('Anlegen fehlgeschlagen', String(e?.message || e));
    } finally {
      setCreating(false);
    }
  };

  return (
    <Modal visible animationType="slide" onRequestClose={onClose} transparent={false}>
      <View style={s.modal}>
        <View style={s.modalHeader}>
          <Text style={s.modalTitle}>Custom OAuth-Provider</Text>
          <TouchableOpacity onPress={onClose} hitSlop={{top:8,bottom:8,left:8,right:8}}>
            <Text style={{color: '#8888AA', fontSize: 18}}>{'✕'}</Text>
          </TouchableOpacity>
        </View>
        <ScrollView style={{flex: 1}} contentContainerStyle={{padding: 16}}>
          <Text style={{color: '#8888AA', fontSize: 12, marginBottom: 12}}>
            Trag die OAuth2-Endpunkte des Anbieters ein. client_id + client_secret
            kommen anschliessend ins Edit-Formular. Die Callback-URL die du beim
            Anbieter eintragen musst, zeigt dir der OAuth-Block im Brain-System-Prompt.
          </Text>

          <Text style={s.label}>Service-Name (z.B. dropbox, discord)</Text>
          <TextInput
            style={s.input}
            value={name}
            onChangeText={setName}
            placeholder="kurz, a-z 0-9 _ -"
            placeholderTextColor="#444460"
            autoCapitalize="none"
            autoCorrect={false}
          />

          <Text style={s.label}>auth_url</Text>
          <TextInput
            style={s.input}
            value={authUrl}
            onChangeText={setAuthUrl}
            placeholder="https://provider.com/oauth/authorize"
            placeholderTextColor="#444460"
            autoCapitalize="none"
            autoCorrect={false}
          />

          <Text style={s.label}>token_url</Text>
          <TextInput
            style={s.input}
            value={tokenUrl}
            onChangeText={setTokenUrl}
            placeholder="https://provider.com/oauth/token"
            placeholderTextColor="#444460"
            autoCapitalize="none"
            autoCorrect={false}
          />

          <Text style={s.label}>scopes (space-separated, optional)</Text>
          <TextInput
            style={s.input}
            value={scopes}
            onChangeText={setScopes}
            placeholder="read write user.email"
            placeholderTextColor="#444460"
            autoCapitalize="none"
            autoCorrect={false}
          />

          <View style={{flexDirection: 'row', gap: 8, marginTop: 20}}>
            <TouchableOpacity style={[s.btn, {backgroundColor: '#1A1A2E', flex: 1}]} onPress={onClose}>
              <Text style={{color: '#8888AA', textAlign: 'center'}}>Abbrechen</Text>
            </TouchableOpacity>
            <TouchableOpacity style={[s.btn, {backgroundColor: '#0096FF', flex: 1}]} onPress={create} disabled={creating}>
              <Text style={{color: '#fff', textAlign: 'center', fontWeight: '700'}}>
                {creating ? '...' : 'Anlegen'}
              </Text>
            </TouchableOpacity>
          </View>
        </ScrollView>
      </View>
    </Modal>
  );
};

// ── Styles ─────────────────────────────────────────────────────────

const s = StyleSheet.create({
  toolbar: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 8,
    paddingHorizontal: 10,
    paddingVertical: 8,
    backgroundColor: '#0D0D1A',
    borderBottomWidth: 1,
    borderBottomColor: '#1E1E2E',
  },
  iconBtn: {
    paddingHorizontal: 10,
    paddingVertical: 5,
    borderRadius: 6,
    backgroundColor: '#1A1A2E',
  },
  row: {
    paddingVertical: 12,
    paddingHorizontal: 14,
    backgroundColor: '#0D0D1A',
    borderBottomWidth: 1,
    borderBottomColor: '#1E1E2E',
  },
  err: {
    color: '#FF6B6B',
    padding: 12,
    fontSize: 12,
  },
  modal: {
    flex: 1,
    backgroundColor: '#0D0D1A',
  },
  modalHeader: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    paddingHorizontal: 16,
    paddingVertical: 12,
    borderBottomWidth: 1,
    borderBottomColor: '#1E1E2E',
  },
  modalTitle: {
    color: '#E0E0F0',
    fontSize: 16,
    fontWeight: '700',
    flex: 1,
    marginRight: 12,
    textTransform: 'capitalize',
  },
  label: {
    color: '#8888AA',
    fontSize: 11,
    fontWeight: '700',
    textTransform: 'uppercase',
    letterSpacing: 0.5,
    marginTop: 12,
    marginBottom: 4,
  },
  input: {
    backgroundColor: '#1A1A2E',
    borderWidth: 1,
    borderColor: '#1E1E2E',
    borderRadius: 6,
    color: '#E0E0F0',
    padding: 10,
    fontSize: 14,
    fontFamily: 'monospace',
  },
  metaBox: {
    backgroundColor: '#1A1A2E',
    borderRadius: 6,
    padding: 10,
    gap: 4,
  },
  meta: {
    color: '#8888AA',
    fontSize: 12,
  },
  btn: {
    paddingHorizontal: 14,
    paddingVertical: 10,
    borderRadius: 6,
    borderWidth: 1,
    borderColor: 'transparent',
  },
});

export default OAuthBrowser;
