import { useState, useEffect } from 'react';
import { AlertTriangle, Info } from 'lucide-react';
import { toast } from 'sonner';
import { api } from '@/api';
import { errMessage, parseUtc } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
import { Toggle } from './adminShared';

interface BankSyncWorker {
  running?: boolean;
  last_run_at?: string | null;
  next_run_at?: string | null;
}

interface BankSyncConfig {
  enabled?: boolean;
  sync_interval_hours?: number;
  sync_days?: number;
  debug_logging?: boolean;
  sync_days_max?: number;
  seed_days?: number;
  worker?: BankSyncWorker;
  encryption_key_source?: string;
}

function timeAgo(iso: string | null | undefined): string | null {
  const d = parseUtc(iso);
  if (!d) return null;
  const secs = Math.floor((Date.now() - d.getTime()) / 1000);
  if (secs < 60)  return 'just now';
  if (secs < 3600) return `${Math.floor(secs / 60)}m ago`;
  if (secs < 86400) return `${Math.floor(secs / 3600)}h ago`;
  return `${Math.floor(secs / 86400)}d ago`;
}

function timeUntil(iso: string | null | undefined): string | null {
  const d = parseUtc(iso);
  if (!d) return null;
  const secs = Math.floor((d.getTime() - Date.now()) / 1000);
  if (secs <= 0) return 'soon';
  if (secs < 60) return `${secs}s`;
  if (secs < 3600) return `${Math.floor(secs / 60)}m`;
  return `${Math.floor(secs / 3600)}h`;
}

export default function BankSyncAdminCard() {
  const [config, setConfig]             = useState<BankSyncConfig | null>(null);
  const [loading, setLoading]           = useState(true);
  const [loadError, setLoadError]       = useState('');
  const [saving, setSaving]             = useState(false);
  const [enabled, setEnabled]           = useState(false);
  const [syncInterval, setSyncInterval] = useState<number | string>(4);
  const [syncDays, setSyncDays]         = useState<number | string>(30);
  const [debugLogging, setDebugLogging] = useState(false);

  useEffect(() => {
    api.bankSyncConfig()
      .then(raw => {
        const d = raw as BankSyncConfig;
        setConfig(d);
        setEnabled(!!d.enabled);
        setSyncInterval(d.sync_interval_hours ?? 4);
        setSyncDays(d.sync_days ?? 30);
        setDebugLogging(!!d.debug_logging);
      })
      .catch(err => setLoadError(errMessage(err, 'Failed to load bank sync config')))
      .finally(() => setLoading(false));
  }, []);

  const handleSave = async () => {
    const hours = parseFloat(String(syncInterval));
    const days  = parseInt(String(syncDays), 10);
    const maxDays = config?.sync_days_max ?? 45;
    if (!Number.isFinite(hours) || hours < 0.5 || hours > 168) {
      toast.error('Sync interval must be between 0.5 and 168 hours.');
      return;
    }
    if (!Number.isFinite(days) || days < 1 || days > maxDays) {
      toast.error(`Routine sync lookback must be 1–${maxDays} days. SimpleFIN Bridge enforces a ${maxDays}-day hard limit — values above ${maxDays} return errors.`);
      return;
    }
    setSaving(true);
    try {
      const result = await api.setBankSyncConfig({ enabled, sync_interval_hours: hours, sync_days: days, debug_logging: debugLogging }) as BankSyncConfig;
      setConfig(result);
      setEnabled(!!result.enabled);
      setSyncInterval(result.sync_interval_hours ?? 4);
      setSyncDays(result.sync_days ?? 30);
      setDebugLogging(!!result.debug_logging);
      toast.success('Bank sync settings saved.');
    } catch (err) {
      toast.error(errMessage(err, 'Failed to update bank sync setting.'));
    } finally {
      setSaving(false);
    }
  };

  if (loading) {
    return (
      <Card>
        <CardContent className="py-8 text-center text-muted-foreground text-sm">
          Loading…
        </CardContent>
      </Card>
    );
  }

  if (loadError) {
    return (
      <Card>
        <CardContent className="py-8 text-center text-sm text-destructive">
          {loadError}
        </CardContent>
      </Card>
    );
  }

  const changed = enabled !== !!config?.enabled
    || parseFloat(String(syncInterval)) !== config?.sync_interval_hours
    || parseInt(String(syncDays), 10) !== config?.sync_days
    || debugLogging !== !!config?.debug_logging;
  const worker = config?.worker;
  const seedDays = config?.seed_days ?? 44;
  const maxDays  = config?.sync_days_max ?? 45;

  return (
    <Card>
      <CardHeader className="pb-4">
        <CardTitle>Bank Sync (SimpleFIN)</CardTitle>
        <p className="text-sm text-muted-foreground mt-1">
          Allow users to connect their own SimpleFIN Bridge account to sync
          read-only bank transactions. Each user manages their own connection
          from the Data page — no bank credentials are stored.
        </p>
      </CardHeader>
      <CardContent className="space-y-5">

        {/* Enable toggle */}
        <div className="flex items-center justify-between">
          <div>
            <p className="text-sm font-medium">Allow users to connect SimpleFIN</p>
            <p className="text-xs text-muted-foreground mt-0.5">
              When enabled, users see a Bank Sync section on their Data page.
            </p>
          </div>
          <Toggle
            checked={enabled}
            onChange={v => setEnabled(v)}
            label="Enable bank sync"
          />
        </div>

        {/* Sync interval */}
        <div className="flex items-center justify-between gap-4">
          <div>
            <p className="text-sm font-medium">Auto-sync interval</p>
            <p className="text-xs text-muted-foreground mt-0.5">
              How often the background worker checks for new transactions.
            </p>
          </div>
          <div className="flex items-center gap-2 shrink-0">
            <Input
              type="number"
              min="0.5"
              max="168"
              step="0.5"
              value={syncInterval}
              onChange={e => setSyncInterval(e.target.value)}
              className="w-20 text-sm text-right"
            />
            <span className="text-sm text-muted-foreground">hrs</span>
          </div>
        </div>

        {/* Sync window — two-mode explainer */}
        <div className="space-y-3">
          <div>
            <p className="text-sm font-medium">Sync lookback windows</p>
            <p className="text-xs text-muted-foreground mt-0.5">
              SimpleFIN uses two different windows depending on sync type.
            </p>
          </div>

          {/* Initial / backfill — read-only */}
          <div className="rounded-lg border border-border/50 bg-muted/20 px-4 py-3 space-y-1">
            <div className="flex items-center justify-between">
              <p className="text-xs font-semibold text-muted-foreground uppercase tracking-wide">
                Initial connect &amp; backfill
              </p>
              <span className="font-mono text-sm font-bold">{seedDays} days</span>
            </div>
            <p className="text-xs text-muted-foreground">
              The first sync (and any manual backfill) fetches up to <strong>{seedDays} days</strong> of
              history to build a complete transaction picture. This is fixed — SimpleFIN Bridge enforces a
              strict <strong>{maxDays}-day hard limit</strong>, so this stays one day under it to avoid
              latency-related errors.
            </p>
          </div>

          {/* Routine sync — editable */}
          <div className="flex items-start justify-between gap-4">
            <div className="flex-1 min-w-0">
              <p className="text-sm font-medium">Routine sync lookback</p>
              <p className="text-xs text-muted-foreground mt-0.5">
                How far back each auto-sync and manual "Sync Now" looks after the initial connect.
                Recommended: <strong>7–30 days</strong>. Setting this near 45 increases request size
                and duplicate-skip work with no benefit once history is established.
              </p>
            </div>
            <div className="flex items-center gap-2 shrink-0">
              <Input
                type="number"
                min="1"
                max={maxDays}
                step="1"
                value={syncDays}
                onChange={e => setSyncDays(Math.min(maxDays, Math.max(1, parseInt(e.target.value, 10) || 30)))}
                className="w-20 text-sm text-right"
              />
              <span className="text-sm text-muted-foreground">days</span>
            </div>
          </div>

          {/* Amber warning at the SimpleFIN limit */}
          {parseInt(String(syncDays), 10) >= maxDays && (
            <div className="flex items-start gap-2 rounded-lg border border-amber-500/30 bg-amber-500/8 px-3 py-2.5">
              <AlertTriangle className="h-3.5 w-3.5 text-amber-500 shrink-0 mt-0.5" />
              <p className="text-xs text-amber-600 dark:text-amber-400">
                {maxDays} days is SimpleFIN Bridge&apos;s maximum. Requests at this limit may occasionally
                fail due to request latency — 30 days or less is recommended for reliable routine syncs.
              </p>
            </div>
          )}

          {/* Always-visible hard-limit note */}
          <div className="flex items-start gap-2 text-xs text-muted-foreground">
            <Info className="h-3.5 w-3.5 shrink-0 mt-0.5" />
            <span>
              SimpleFIN Bridge enforces a <strong>{maxDays}-day maximum</strong> on all requests.
              Any value above {maxDays} will cause sync errors for all users.
            </span>
          </div>
        </div>

        {/* Auto-sync worker status */}
        {config?.enabled && worker && (
          <div className="rounded-lg border border-border/60 bg-muted/20 px-4 py-3 space-y-2">
            <p className="text-xs font-semibold uppercase tracking-widest text-muted-foreground">Auto-sync worker</p>
            <div className="grid grid-cols-2 gap-x-6 gap-y-1 text-sm sm:grid-cols-3">
              <div>
                <p className="text-xs text-muted-foreground">Status</p>
                <p className="font-medium flex items-center gap-1.5">
                  <span className={`h-1.5 w-1.5 rounded-full ${worker.running ? 'bg-amber-500 animate-pulse' : 'bg-emerald-500'}`} />
                  {worker.running ? 'Running' : 'Idle'}
                </p>
              </div>
              <div>
                <p className="text-xs text-muted-foreground">Last run</p>
                <p className="font-medium">{worker.last_run_at ? timeAgo(worker.last_run_at) : '—'}</p>
              </div>
              <div>
                <p className="text-xs text-muted-foreground">Next run</p>
                <p className="font-medium">{worker.next_run_at ? `in ${timeUntil(worker.next_run_at)}` : '—'}</p>
              </div>
            </div>
          </div>
        )}

        {/* Debug logging toggle */}
        <div className="flex items-center justify-between border-t border-border/50 pt-4">
          <div>
            <p className="text-sm font-medium">Debug logging</p>
            <p className="text-xs text-muted-foreground mt-0.5">
              Logs each account, transaction, and auto-match step to the server console.
              Turn on to diagnose sync issues, then off when done.
            </p>
          </div>
          <Toggle
            checked={debugLogging}
            onChange={v => setDebugLogging(v)}
            label="Enable debug logging"
          />
        </div>

        {/* Encryption note */}
        <p className="text-xs text-muted-foreground border-t border-border/50 pt-3">
          {config?.encryption_key_source === 'env'
            ? <>SimpleFIN credentials are encrypted at rest. Encryption key is loaded from <code className="font-mono">TOKEN_ENCRYPTION_KEY</code> — stored separately from the database, so a database backup alone cannot decrypt credentials.</>
            : <>SimpleFIN credentials are encrypted, but the key is stored in the same database as the data. A database backup or file-level read includes everything needed to decrypt credentials. Set <code className="font-mono">TOKEN_ENCRYPTION_KEY</code> in your environment to keep the key separate.</>
          }{' '}
          Regular database backups preserve all user connections.
        </p>

        <div className="flex justify-end">
          <Button onClick={handleSave} disabled={saving || !changed}>
            {saving ? 'Saving…' : 'Save'}
          </Button>
        </div>

      </CardContent>
    </Card>
  );
}
