/**
 * Redmine Settings View
 *
 * Configure the Redmine connection for this feature instance:
 *   - Base URL, Project ID, API Key, Root Tracker name
 *   - "Verbindung testen" -- calls whoAmI + getProject and reports the result
 *   - "Sync starten" -- pulls all (or only changed) tickets into the local mirror
 *
 * The user tests the feature directly here in Porta -- no pytest sandbox.
 */

import React, { useCallback, useEffect, useState } from 'react';

import { useApiRequest } from '../../../hooks/useApi';
import { useInstanceId } from '../../../hooks/useCurrentInstance';
import { useLanguage } from '../../../providers/language/LanguageContext';
import {
  RedmineConfigDto,
  RedmineConnectionTestResult,
  RedmineSyncResult,
  RedmineSyncStatus,
  deleteRedmineConfigApi,
  getRedmineConfigApi,
  getRedmineSyncStatusApi,
  runRedmineSyncApi,
  testRedmineConnectionApi,
  updateRedmineConfigApi,
} from '../../../api/redmineApi';

import styles from './RedmineViews.module.css';

const _formatTs = (ts?: number | null): string => {
  if (!ts) return '-';
  try {
    return new Date(ts * 1000).toLocaleString();
  } catch {
    return String(ts);
  }
};

const _formatDuration = (ms?: number | null): string => {
  if (ms == null) return '-';
  if (ms < 1000) return `${ms} ms`;
  const s = ms / 1000;
  if (s < 60) return `${s.toFixed(1)} s`;
  const m = s / 60;
  return `${m.toFixed(1)} min`;
};

export const RedmineSettingsView: React.FC = () => {
  const { t } = useLanguage();
  const { request } = useApiRequest();
  const instanceId = useInstanceId();

  const [config, setConfig] = useState<RedmineConfigDto | null>(null);
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [testing, setTesting] = useState(false);
  const [syncing, setSyncing] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [success, setSuccess] = useState<string | null>(null);
  const [testResult, setTestResult] = useState<RedmineConnectionTestResult | null>(null);
  const [syncResult, setSyncResult] = useState<RedmineSyncResult | null>(null);
  const [syncStatus, setSyncStatus] = useState<RedmineSyncStatus | null>(null);

  const [baseUrl, setBaseUrl] = useState('');
  const [projectId, setProjectId] = useState('');
  const [rootTrackerName, setRootTrackerName] = useState('Userstory');
  const [apiKey, setApiKey] = useState('');

  const _hydrate = useCallback((c: RedmineConfigDto) => {
    setConfig(c);
    setBaseUrl(c.baseUrl || '');
    setProjectId(c.projectId || '');
    setRootTrackerName(c.rootTrackerName || 'Userstory');
  }, []);

  const _loadStatus = useCallback(async () => {
    if (!instanceId) return;
    try {
      const status = await getRedmineSyncStatusApi(request, instanceId);
      setSyncStatus(status);
    } catch {
      // status is optional; don't block the page on failure
    }
  }, [request, instanceId]);

  useEffect(() => {
    if (!instanceId) return;
    let cancelled = false;
    (async () => {
      setLoading(true);
      try {
        const cfg = await getRedmineConfigApi(request, instanceId);
        if (!cancelled) _hydrate(cfg);
        await _loadStatus();
      } catch (e: any) {
        if (!cancelled) setError(e?.message || t('Fehler beim Laden'));
      } finally {
        if (!cancelled) setLoading(false);
      }
    })();
    return () => { cancelled = true; };
  }, [request, instanceId, _hydrate, _loadStatus, t]);

  const _save = useCallback(async () => {
    if (!instanceId) return;
    setSaving(true);
    setError(null);
    setSuccess(null);
    try {
      const body: Record<string, any> = {
        baseUrl: baseUrl.trim(),
        projectId: projectId.trim(),
        rootTrackerName: rootTrackerName.trim() || 'Userstory',
        isActive: true,
      };
      if (apiKey.trim() !== '') body.apiKey = apiKey.trim();
      const updated = await updateRedmineConfigApi(request, instanceId, body);
      _hydrate(updated);
      setApiKey('');
      setSuccess(t('Einstellungen gespeichert.'));
      setTimeout(() => setSuccess(null), 3000);
    } catch (e: any) {
      setError(e?.message || t('Fehler beim Speichern.'));
    } finally {
      setSaving(false);
    }
  }, [request, instanceId, baseUrl, projectId, rootTrackerName, apiKey, _hydrate, t]);

  const _test = useCallback(async () => {
    if (!instanceId) return;
    setTesting(true);
    setError(null);
    setTestResult(null);
    try {
      const result = await testRedmineConnectionApi(request, instanceId);
      setTestResult(result);
    } catch (e: any) {
      setError(e?.message || t('Verbindungstest fehlgeschlagen.'));
    } finally {
      setTesting(false);
    }
  }, [request, instanceId, t]);

  const _runSync = useCallback(async (force: boolean) => {
    if (!instanceId) return;
    setSyncing(true);
    setError(null);
    setSuccess(null);
    setSyncResult(null);
    try {
      const result = await runRedmineSyncApi(request, instanceId, force);
      setSyncResult(result);
      await _loadStatus();
      const cfg = await getRedmineConfigApi(request, instanceId);
      _hydrate(cfg);
      setSuccess(
        t('Sync erfolgreich.') +
          ` ${result.ticketsUpserted} ${t('Tickets')}, ${result.relationsUpserted} ${t('Beziehungen')}, ${_formatDuration(result.durationMs)}.`,
      );
    } catch (e: any) {
      setError(e?.message || t('Sync fehlgeschlagen.'));
    } finally {
      setSyncing(false);
    }
  }, [request, instanceId, _loadStatus, _hydrate, t]);

  const _delete = useCallback(async () => {
    if (!instanceId) return;
    if (!window.confirm(t('Konfiguration wirklich loeschen? Der lokale Mirror bleibt erhalten.'))) return;
    setError(null);
    setSuccess(null);
    try {
      await deleteRedmineConfigApi(request, instanceId);
      setBaseUrl('');
      setProjectId('');
      setRootTrackerName('Userstory');
      setApiKey('');
      setConfig(null);
      setSuccess(t('Konfiguration geloescht.'));
    } catch (e: any) {
      setError(e?.message || t('Loeschen fehlgeschlagen.'));
    }
  }, [request, instanceId, t]);

  if (loading) {
    return <div className={styles.loading}>{t('Einstellungen werden geladen ...')}</div>;
  }

  const canTest = !!config?.hasApiKey && !!baseUrl && !!projectId;
  const canSync = canTest;

  return (
    <div className={styles.page}>
      <h2 className={styles.heading}>{t('Redmine -- Einstellungen')}</h2>
      <p className={styles.subheading}>
        {t('Verbindung dieser Feature-Instanz zu einem Redmine-Projekt. Speichern, testen, dann initialen Sync starten.')}
      </p>

      {error && <div className={styles.alertErr}>{error}</div>}
      {success && <div className={styles.alertOk}>{success}</div>}

      <div className={styles.section}>
        <h3 className={styles.sectionTitle}>{t('Verbindung')}</h3>

        <div className={styles.field}>
          <label className={styles.label}>{t('Basis-URL')}</label>
          <input
            type="text"
            className={styles.input}
            value={baseUrl}
            onChange={e => setBaseUrl(e.target.value)}
            placeholder="https://redmine.example.com"
            spellCheck={false}
          />
          <div className={styles.hint}>{t('Ohne abschliessenden Slash, z.B. https://redmine.logobject.ch')}</div>
        </div>

        <div className={styles.field}>
          <label className={styles.label}>{t('Projekt-ID oder -Slug')}</label>
          <input
            type="text"
            className={styles.input}
            value={projectId}
            onChange={e => setProjectId(e.target.value)}
            placeholder="logobject-mars"
            spellCheck={false}
          />
        </div>

        <div className={styles.field}>
          <label className={styles.label}>{t('Wurzel-Tracker (Name)')}</label>
          <input
            type="text"
            className={styles.input}
            value={rootTrackerName}
            onChange={e => setRootTrackerName(e.target.value)}
            placeholder="Userstory"
            spellCheck={false}
          />
          <div className={styles.hint}>
            {t('Tracker, der die Wurzel der Ticket-Hierarchie bildet. Wird beim Sync gegen die Tracker-Liste aufgeloest.')}
          </div>
        </div>

        <div className={styles.field}>
          <label className={styles.label}>{t('API-Key')}</label>
          <input
            type="password"
            className={styles.input}
            value={apiKey}
            onChange={e => setApiKey(e.target.value)}
            placeholder={config?.hasApiKey ? t('(gesetzt -- leer lassen, um nicht zu aendern)') : t('Redmine API Access Key')}
            spellCheck={false}
            autoComplete="new-password"
          />
          <div className={styles.hint}>
            {t('Wird verschluesselt gespeichert. Status: ')}
            {config?.hasApiKey ? <strong>{t('gesetzt')}</strong> : <em>{t('nicht gesetzt')}</em>}
          </div>
        </div>

        <div className={styles.row}>
          <button className={styles.btn} onClick={_save} disabled={saving}>
            {saving ? t('Speichere ...') : t('Speichern')}
          </button>
          <button className={styles.btnSecondary} onClick={_test} disabled={!canTest || testing}>
            {testing ? t('Teste ...') : t('Verbindung testen')}
          </button>
          {config?.id && (
            <button className={styles.btnDanger} onClick={_delete}>
              {t('Konfiguration loeschen')}
            </button>
          )}
        </div>

        {testResult && (
          <div style={{ marginTop: '0.85rem' }}>
            {testResult.ok ? (
              <div className={styles.alertOk}>
                <strong>{t('Verbindung OK')}.</strong>{' '}
                {testResult.user?.name && <>{t('Angemeldet als')} <strong>{testResult.user.name}</strong>. </>}
                {testResult.project?.name && <>{t('Projekt')}: <strong>{testResult.project.name}</strong>.</>}
              </div>
            ) : (
              <div className={styles.alertErr}>
                <strong>{t('Verbindung fehlgeschlagen')}.</strong>{' '}
                {testResult.message || testResult.reason || ''}
                {testResult.status ? ` (HTTP ${testResult.status})` : ''}
              </div>
            )}
          </div>
        )}
      </div>

      <div className={styles.section}>
        <h3 className={styles.sectionTitle}>{t('Mirror-Sync')}</h3>
        <p className={styles.hint} style={{ marginBottom: '0.85rem' }}>
          {t('Tickets werden in die lokale Datenbank gespiegelt, damit Statistik und Browser auch bei 20\u2019000+ Tickets schnell sind. Nach Aenderungen wird das Mirror-Bild automatisch nachgezogen.')}
        </p>

        <div className={styles.kvGrid} style={{ marginBottom: '0.85rem' }}>
          <div className={styles.kvLabel}>{t('Letzter Sync')}:</div>
          <div className={styles.kvValue}>{_formatTs(config?.lastSyncAt)}</div>
          <div className={styles.kvLabel}>{t('Letzter Full-Sync')}:</div>
          <div className={styles.kvValue}>{_formatTs(config?.lastFullSyncAt)}</div>
          <div className={styles.kvLabel}>{t('Letzte Sync-Dauer')}:</div>
          <div className={styles.kvValue}>{_formatDuration(syncStatus?.lastSyncDurationMs)}</div>
          <div className={styles.kvLabel}>{t('Tickets im Mirror')}:</div>
          <div className={styles.kvValue}>{syncStatus?.mirroredTicketCount ?? '-'}</div>
          <div className={styles.kvLabel}>{t('Beziehungen im Mirror')}:</div>
          <div className={styles.kvValue}>{syncStatus?.mirroredRelationCount ?? '-'}</div>
          {config?.lastSyncErrorMessage && (
            <>
              <div className={styles.kvLabel}>{t('Letzter Fehler')}:</div>
              <div className={styles.kvValue} style={{ color: '#c53030' }}>{config.lastSyncErrorMessage}</div>
            </>
          )}
        </div>

        <div className={styles.row}>
          <button className={styles.btn} onClick={() => _runSync(false)} disabled={!canSync || syncing}>
            {syncing ? t('Synchronisiere ...') : t('Sync starten (inkrementell)')}
          </button>
          <button className={styles.btnSecondary} onClick={() => _runSync(true)} disabled={!canSync || syncing}>
            {t('Full-Sync (alle Tickets)')}
          </button>
        </div>

        {syncResult && (
          <div className={styles.alertInfo} style={{ marginTop: '0.85rem' }}>
            <strong>{syncResult.full ? t('Full-Sync') : t('Inkrementeller Sync')}:</strong>{' '}
            {syncResult.ticketsUpserted} {t('Tickets')}, {syncResult.relationsUpserted}{' '}
            {t('Beziehungen')} in {_formatDuration(syncResult.durationMs)}.
          </div>
        )}

        {!canSync && (
          <div className={styles.hint} style={{ marginTop: '0.85rem' }}>
            {t('Bitte zuerst Basis-URL, Projekt-ID und API-Key speichern.')}
          </div>
        )}
      </div>
    </div>
  );
};

export default RedmineSettingsView;
