import React, { useState, useEffect, useCallback } from 'react';
import { Link } from 'react-router-dom';
import {
  Activity, AlertCircle, ArrowUpCircle, BarChart3, Bell, CalendarClock,
  CheckCircle2, Clock, Cpu, Database, Globe, HardDrive, Landmark,
  RefreshCw, ScrollText, Wrench,
} from 'lucide-react';
import { toast } from 'sonner';
import { api } from '@/api';
import { cn, fmtUptime, fmtBytes } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { MarkdownText } from '@/components/MarkdownText';

// ─── Helpers ──────────────────────────────────────────────────────────────────

function formatMemory(runtime) {
  if (runtime.memory_used_bytes ?? runtime.memory?.used ?? runtime.memory) {
    return fmtBytes(runtime.memory_used_bytes ?? runtime.memory?.used ?? runtime.memory);
  }
  if (runtime.memory_mb) return `${runtime.memory_mb} MB`;
  return null;
}

function formatBytesMaybe(value) {
  return value === undefined || value === null ? null : fmtBytes(value);
}

function formatDateTime(value) {
  if (!value) return null;
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return value;
  return date.toLocaleString();
}

// ─── Design primitives ────────────────────────────────────────────────────────

function SectionLabel({ children }) {
  return (
    <div className="flex items-center gap-3 mb-3 mt-8 first:mt-0">
      <span className="text-[11px] font-semibold uppercase tracking-widest text-muted-foreground/50 whitespace-nowrap">
        {children}
      </span>
      <div className="flex-1 h-px bg-border/40" />
    </div>
  );
}

function StatRow({ label, value, last }) {
  return (
    <div className={cn('flex items-center justify-between py-1.5 gap-3', !last && 'border-b border-border/40')}>
      <span className="text-xs text-muted-foreground shrink-0">{label}</span>
      <span className="text-xs font-medium tabular-nums text-right truncate max-w-[60%]">
        {value ?? <span className="text-muted-foreground/50">—</span>}
      </span>
    </div>
  );
}

function StatusPill({ tone = 'muted', children }) {
  const cls = {
    good:  'bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border-emerald-500/25',
    warn:  'bg-amber-500/10 text-amber-600 dark:text-amber-400 border-amber-400/30',
    bad:   'bg-red-500/10 text-red-600 dark:text-red-400 border-red-500/25',
    muted: 'bg-muted/60 text-muted-foreground border-border',
  }[tone] ?? 'bg-muted/60 text-muted-foreground border-border';

  return (
    <span className={cn(
      'inline-flex items-center shrink-0 rounded border px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide',
      cls,
    )}>
      {children}
    </span>
  );
}

function StatusCard({ title, icon: Icon, status, tone = 'muted', children, className }) {
  const accentCls = {
    good:  'border-t-emerald-500/60',
    warn:  'border-t-amber-400/70',
    bad:   'border-t-red-500/60',
    muted: 'border-t-border/60',
  }[tone] ?? 'border-t-border/60';

  return (
    <div className={cn(
      'flex flex-col bg-card rounded-xl border border-border border-t-[3px] shadow-sm',
      accentCls,
      className,
    )}>
      <div className="flex items-center justify-between gap-2 px-5 pt-4 pb-3 border-b border-border/30">
        <div className="flex items-center gap-2 min-w-0">
          {Icon && <Icon className="h-3.5 w-3.5 shrink-0 text-muted-foreground/50" />}
          <h3 className="text-[11px] font-bold uppercase tracking-widest text-muted-foreground/80 truncate">
            {title}
          </h3>
        </div>
        {status != null && <StatusPill tone={tone}>{status}</StatusPill>}
      </div>
      <div className="px-5 py-3 flex-1">{children}</div>
    </div>
  );
}

function SkeletonCard() {
  return (
    <div className="flex flex-col bg-card rounded-xl border border-border border-t-[3px] border-t-border/60 shadow-sm animate-pulse">
      <div className="flex items-center justify-between gap-2 px-5 pt-4 pb-3 border-b border-border/30">
        <div className="flex items-center gap-2">
          <div className="h-3.5 w-3.5 rounded bg-muted/70" />
          <div className="h-3 w-20 rounded bg-muted/70" />
        </div>
        <div className="h-4 w-14 rounded bg-muted/50" />
      </div>
      <div className="px-5 py-3 space-y-0">
        {[1, 2, 3].map(i => (
          <div key={i} className="flex justify-between items-center py-1.5 border-b border-border/40 last:border-0">
            <div className="h-3 w-20 rounded bg-muted/60" />
            <div className="h-3 w-14 rounded bg-muted/50" />
          </div>
        ))}
      </div>
    </div>
  );
}

// ─── Update Card ──────────────────────────────────────────────────────────────

const CATEGORY_ORDER = ['Added', 'Changed', 'Fixed', 'Removed', 'Deprecated', 'Security'];

function UpdateCard({ update, onCheckNow, checking }) {
  const hasUpdate = !!update.has_update;
  const isKnown   = update.up_to_date !== null && update.up_to_date !== undefined;
  const hasError  = !!update.error;

  const tone   = hasUpdate ? 'warn' : isKnown && !hasError ? 'good' : 'muted';
  const status = hasUpdate      ? 'Update Available'
    : hasError                  ? 'Check Failed'
    : isKnown                   ? 'Up to Date'
    : 'Unknown';

  const StatusIcon = hasUpdate ? ArrowUpCircle : hasError ? AlertCircle : CheckCircle2;
  const iconCls    = hasUpdate ? 'text-amber-500' : hasError ? 'text-red-500' : isKnown ? 'text-emerald-500' : 'text-muted-foreground';

  return (
    <StatusCard title="Software Update" icon={RefreshCw} status={status} tone={tone}>
      <div className="flex items-center gap-2 py-1.5 border-b border-border/40">
        <StatusIcon className={cn('h-3.5 w-3.5 shrink-0', iconCls)} />
        <span className="text-xs font-medium">
          {hasUpdate            ? `v${update.latest_version} is available`
            : isKnown && !hasError ? 'Running the latest version'
            : hasError            ? 'Could not reach update server'
            : 'Update status unknown'}
        </span>
      </div>
      <StatRow label="Running" value={update.current_version ? `v${update.current_version}` : null} />
      <div className="flex items-center justify-between py-1.5 border-b border-border/40 gap-3">
        <span className="text-xs text-muted-foreground shrink-0">Latest</span>
        {update.latest_version ? (
          update.latest_release_url ? (
            <a href={update.latest_release_url} target="_blank" rel="noopener noreferrer"
              className={cn('text-xs font-medium underline-offset-2 hover:underline truncate', hasUpdate ? 'text-amber-500' : '')}>
              v{update.latest_version} ↗
            </a>
          ) : (
            <span className="text-xs font-medium">v{update.latest_version}</span>
          )
        ) : (
          <span className="text-xs text-muted-foreground/50">—</span>
        )}
      </div>
      <StatRow label="Last Checked" value={formatDateTime(update.last_checked_at)} />
      {update.error && (
        <p className="text-[11px] text-red-400 leading-relaxed pt-1.5">{update.error}</p>
      )}
      <div className="pt-3">
        <Button variant="outline" size="sm" onClick={onCheckNow} disabled={checking}
          className="h-7 text-xs gap-1.5">
          <RefreshCw className={cn('h-3 w-3', checking && 'animate-spin')} />
          {checking ? 'Checking…' : 'Check Now'}
        </Button>
      </div>
    </StatusCard>
  );
}

// ─── Release Notes Card ───────────────────────────────────────────────────────

function ReleaseNotesCard({ version, historyMeta }) {
  if (!version) return <SkeletonCard />;

  const grouped = CATEGORY_ORDER.reduce((acc, cat) => {
    const notes = version.notes?.filter(n => n.category === cat) ?? [];
    if (notes.length) acc[cat] = notes;
    return acc;
  }, {});
  version.notes?.forEach(n => {
    if (!grouped[n.category]) grouped[n.category] = [...(grouped[n.category] ?? []), n];
  });

  const categories = Object.keys(grouped);
  const preview = categories.length ? grouped[categories[0]]?.[0]?.text : null;

  return (
    <StatusCard title="Release Notes" icon={ScrollText} status={`v${version.version}`} tone="good">
      <StatRow label="Total Changes" value={version.notes?.length ? `${version.notes.length} items` : null} />
      <StatRow label="Last Updated"  value={formatDateTime(historyMeta?.updated_at)} />
      <div className="py-1.5 border-b border-border/40">
        <p className="text-[11px] text-muted-foreground/60 uppercase tracking-wide mb-1">Preview</p>
        <p className="text-xs font-medium line-clamp-2 leading-relaxed">
          <MarkdownText text={preview ?? 'No release notes available.'} />
        </p>
      </div>
      <div className="pt-3">
        <Button asChild variant="outline" size="sm" className="h-7 text-xs">
          <Link to="/release-notes">View Full Notes</Link>
        </Button>
      </div>
    </StatusCard>
  );
}

// ─── StatusPage ───────────────────────────────────────────────────────────────

export default function StatusPage() {
  const [data, setData]                     = useState(null);
  const [version, setVersion]               = useState(null);
  const [historyMeta, setHistoryMeta]       = useState(null);
  const [loading, setLoading]               = useState(true);
  const [updateData, setUpdateData]         = useState(null);
  const [updateChecking, setUpdateChecking] = useState(false);

  const load = useCallback(async () => {
    setLoading(true);
    setVersion(null);
    setHistoryMeta(null);
    try {
      const [statusData, versionData] = await Promise.all([api.status(), api.version()]);
      setData(statusData);
      setUpdateData(statusData?.update ?? null);
      setVersion(versionData);
      try {
        const historyData = await api.releaseHistory();
        setHistoryMeta({ version: historyData.version, updated_at: historyData.updated_at });
      } catch { setHistoryMeta(null); }
    } catch (err) {
      toast.error(err.message || 'Failed to load status.');
    } finally {
      setLoading(false);
    }
  }, []);

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

  const handleCheckNow = useCallback(async () => {
    setUpdateChecking(true);
    try {
      setUpdateData(await api.checkForUpdates());
    } catch (err) {
      toast.error(err.message || 'Update check failed');
    } finally {
      setUpdateChecking(false);
    }
  }, []);

  // Normalize the nested response shape
  const app           = data?.application  ?? data?.app  ?? {};
  const rt            = data?.runtime      ?? {};
  const db            = data?.database     ?? data?.db   ?? {};
  const stats         = data?.statistics   ?? data?.stats ?? {};
  const worker        = data?.worker       ?? data?.jobs ?? {};
  const notifications = data?.notifications ?? data?.email ?? {};
  const backups       = data?.backups      ?? data?.backup ?? {};
  const server        = data?.server       ?? data?.clock ?? {};
  const tracker       = data?.tracker      ?? data?.tracker_health ?? {};
  const cleanup       = data?.cleanup      ?? {};
  const bankSync      = data?.bank_sync    ?? data?.simplefin ?? {};
  const errors        = data?.errors       ?? data?.recent_errors ?? [];

  const dbOk                   = db.connected ?? (db.status === 'connected') ?? true;
  const workerOk               = !worker.enabled ? null : worker.last_error ? false : true;
  const notificationsConfigured = notifications.configured ?? notifications.smtp_configured ?? null;
  const backupsEnabled          = backups.enabled ?? null;
  const backupsScheduled        = backups.scheduled_enabled ?? null;
  const backupsStatus = backupsEnabled === null  ? 'Pending'
    : !backupsEnabled                            ? 'Disabled'
    : backupsScheduled                           ? 'Scheduled'
    : 'Manual Only';
  const backupsTone   = backupsEnabled === null  ? 'muted'
    : !backupsEnabled                            ? 'warn'
    : backupsScheduled                           ? 'good'
    : 'warn';
  const recentErrors           = Array.isArray(errors) ? errors : [];

  const bankSyncEnabled = bankSync.enabled ?? false;
  const bankSyncStatus  = !bankSyncEnabled     ? 'Disabled'
    : bankSync.running                          ? 'Syncing'
    : bankSync.last_error                       ? 'Error'
    : (bankSync.source_count ?? 0) > 0         ? 'Connected'
    : 'No Sources';
  const bankSyncTone = !bankSyncEnabled         ? 'muted'
    : bankSync.last_error                       ? 'warn'
    : (bankSync.source_count ?? 0) > 0         ? 'good'
    : 'warn';

  const utcOffset = server.utc_offset != null
    ? `UTC${server.utc_offset >= 0 ? '+' : ''}${server.utc_offset}`
    : null;

  return (
    <div>

      {/* ── Page header ──────────────────────────────────────────────── */}
      <div className="flex flex-col gap-3 mb-6 sm:flex-row sm:items-start sm:justify-between">
        <div>
          <h1 className="text-2xl font-bold tracking-tight">Server Status</h1>
          <p className="text-sm text-muted-foreground mt-0.5">Health and operational status</p>
        </div>
        <Button variant="outline" size="sm" onClick={load} disabled={loading} className="self-start">
          <RefreshCw className={cn('h-3.5 w-3.5 mr-1.5', loading && 'animate-spin')} />
          Refresh
        </Button>
      </div>

      {/* ── Health banner ────────────────────────────────────────────── */}
      {!loading && data && (
        <div className={cn(
          'flex items-center gap-3 px-4 py-2.5 rounded-lg border mb-6',
          data.ok
            ? 'bg-emerald-500/5 border-emerald-500/20'
            : 'bg-red-500/5 border-red-500/20',
        )}>
          <span className={cn(
            'h-2 w-2 rounded-full shrink-0',
            data.ok
              ? 'bg-emerald-500 shadow-[0_0_0_3px_rgb(34_197_94/0.15)]'
              : 'bg-red-500 shadow-[0_0_0_3px_rgb(239_68_68/0.15)]',
          )} />
          <span className={cn(
            'text-sm font-semibold',
            data.ok ? 'text-emerald-700 dark:text-emerald-400' : 'text-red-600 dark:text-red-400',
          )}>
            {data.ok ? 'All systems operational' : 'One or more systems need attention'}
          </span>
          <div className="ml-auto hidden sm:flex items-center gap-4 text-xs text-muted-foreground tabular-nums">
            {(app.version ?? data?.version) && <span>v{app.version ?? data?.version}</span>}
            <span>{fmtUptime(app.uptime_seconds ?? data?.uptime_seconds ?? 0)} uptime</span>
          </div>
        </div>
      )}

      {/* ── Loading skeleton ─────────────────────────────────────────── */}
      {loading ? (
        <>
          {[3, 5].map((count, si) => (
            <React.Fragment key={si}>
              <div className={cn('flex items-center gap-3 mb-3', si > 0 && 'mt-8')}>
                <div className="h-2.5 w-24 rounded bg-muted/60 animate-pulse" />
                <div className="flex-1 h-px bg-border/40" />
              </div>
              <div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-3 mb-2">
                {Array.from({ length: count }).map((_, i) => <SkeletonCard key={i} />)}
              </div>
            </React.Fragment>
          ))}
        </>
      ) : (
        <>

          {/* ── Infrastructure ─────────────────────────────────────────── */}
          <SectionLabel>Infrastructure</SectionLabel>
          <div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-3">

            <StatusCard title="Application" icon={Globe}
              status={data?.ok ? 'Online' : 'Degraded'}
              tone={data?.ok ? 'good' : 'bad'}
            >
              <StatRow label="Version"     value={(app.version ?? data?.version) ? `v${app.version ?? data?.version}` : null} />
              <StatRow label="Environment" value={app.environment ?? app.env ?? data?.environment ?? data?.env} />
              <StatRow label="Uptime"      value={fmtUptime(app.uptime_seconds ?? app.uptime ?? data?.uptime_seconds ?? 0)} last />
            </StatusCard>

            <StatusCard title="Database" icon={Database}
              status={dbOk ? 'Connected' : 'Error'}
              tone={dbOk ? 'good' : 'bad'}
            >
              <StatRow label="Size"          value={formatBytesMaybe(db.size_bytes ?? db.size)} />
              <StatRow label="Last Modified" value={formatDateTime(db.last_modified ?? db.modified_at)} />
              {dbOk
                ? <StatRow label="Health" value="Healthy" last />
                : <StatRow label="Error"  value={db.last_error} last />}
            </StatusCard>

            <StatusCard title="Runtime" icon={Cpu}>
              <StatRow label="Node.js"       value={rt.node_version ?? rt.node ?? data?.node_version} />
              <StatRow label="Platform"      value={rt.platform ?? data?.platform} />
              <StatRow label="Architecture"  value={rt.arch ?? data?.arch} />
              <StatRow label="Memory"        value={formatMemory(rt)} last />
            </StatusCard>

          </div>

          {/* ── Services ───────────────────────────────────────────────── */}
          <SectionLabel>Services</SectionLabel>
          <div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-3">

            <StatusCard title="Daily Worker" icon={CalendarClock}
              status={workerOk === null ? 'Pending' : workerOk ? 'Running' : 'Error'}
              tone={workerOk === null ? 'muted' : workerOk ? 'good' : 'bad'}
            >
              <StatRow label="Enabled"    value={worker.enabled === undefined ? null : worker.enabled ? 'Yes' : 'No'} />
              <StatRow label="Last Run"   value={formatDateTime(worker.last_run_at ?? worker.last_success_at)} />
              <StatRow label="Next Run"   value={formatDateTime(worker.next_run_at)} />
              <StatRow label="Last Error" value={worker.last_error} last />
            </StatusCard>

            <StatusCard title="SimpleFIN Sync" icon={Landmark}
              status={bankSyncStatus}
              tone={bankSyncTone}
            >
              <StatRow label="Connections" value={bankSyncEnabled ? (bankSync.source_count ?? 0) : null} />
              <StatRow label="Accounts"    value={bankSyncEnabled ? (bankSync.account_count ?? 0) : null} />
              <StatRow label="Last Sync"   value={bankSyncEnabled ? formatDateTime(bankSync.last_sync_at) : null} />
              <StatRow label="Next Check"  value={bankSyncEnabled ? formatDateTime(bankSync.next_run_at) : null} />
              <StatRow label="Interval"    value={bankSyncEnabled && bankSync.interval_hours ? `Every ${bankSync.interval_hours}h` : null} />
              <StatRow label="Last Error"  value={bankSync.last_error} last />
            </StatusCard>

            <StatusCard title="Notifications" icon={Bell}
              status={notificationsConfigured === null ? 'Pending' : notificationsConfigured ? 'Configured' : 'Missing'}
              tone={notificationsConfigured === null ? 'muted' : notificationsConfigured ? 'good' : 'warn'}
            >
              <StatRow label="Enabled"   value={notifications.enabled === undefined ? null : notifications.enabled ? 'Yes' : 'No'} />
              <StatRow label="SMTP"      value={notificationsConfigured == null ? null : notificationsConfigured ? 'Configured' : 'Not configured'} />
              <StatRow label="Last Sent" value={formatDateTime(notifications.last_sent_at)} />
              <StatRow label="Failures"  value={notifications.failures ?? notifications.failed_count} last />
            </StatusCard>

            <StatusCard title="Backups" icon={HardDrive}
              status={backupsStatus}
              tone={backupsTone}
            >
              <StatRow label="Schedule"
                value={
                  backupsEnabled === null ? null
                  : !backupsEnabled       ? 'Disabled'
                  : backupsScheduled      ? `${backups.scheduled_frequency ?? ''} ${backups.scheduled_time ?? ''}`.trim() || 'Enabled'
                  : 'Not scheduled'
                }
              />
              <StatRow label="Last Backup"  value={formatDateTime(backups.last_backup_at)} />
              <StatRow label="Next Backup"  value={formatDateTime(backups.next_backup_at)} />
              <StatRow label="Count"        value={backups.count ?? backups.backup_count} />
              <StatRow label="Retention"    value={backups.keep_count ?? backups.retention_count} />
              <StatRow label="Last Error"   value={backups.last_error} last />
            </StatusCard>

            <StatusCard title="Maintenance" icon={Wrench}
              status={cleanup.last_run_at ? 'OK' : 'Pending'}
              tone={cleanup.last_run_at ? 'good' : 'muted'}
            >
              <StatRow label="Last Run"        value={formatDateTime(cleanup.last_run_at)} />
              <StatRow label="Import Sessions" value={cleanup.last_result?.import_sessions?.pruned != null ? `${cleanup.last_result.import_sessions.pruned} pruned` : null} />
              <StatRow label="Temp Files"      value={cleanup.last_result?.temp_export_files?.removed != null ? `${cleanup.last_result.temp_export_files.removed} removed` : null} />
              <StatRow label="Backup Partials" value={cleanup.last_result?.backup_partials?.removed != null ? `${cleanup.last_result.backup_partials.removed} removed` : null} last />
            </StatusCard>

          </div>

          {/* ── App Health ─────────────────────────────────────────────── */}
          <SectionLabel>App Health</SectionLabel>
          <div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-3">

            <StatusCard title="Tracker" icon={Activity}>
              <StatRow label="Bills This Month"    value={tracker.bills_this_month} />
              <StatRow label="Payments This Month" value={tracker.payments_this_month} />
              <StatRow label="Overdue"             value={tracker.overdue_count} />
              <StatRow label="Skipped"             value={tracker.skipped_count} last />
            </StatusCard>

            <StatusCard title="Statistics" icon={BarChart3}>
              <StatRow label="Active Bills"   value={stats.active_bills ?? stats.bills ?? stats.active_bill_count} />
              <StatRow label="Total Payments" value={stats.total_payments ?? stats.payments} />
              <StatRow label="Users"          value={stats.users ?? stats.user_count} />
              <StatRow label="Sessions"       value={stats.active_sessions ?? stats.sessions} last />
            </StatusCard>

            <StatusCard title="Server Clock" icon={Clock}>
              <StatRow label="Server Time" value={formatDateTime(server.now ?? data?.server_time)} />
              <StatRow label="Date"        value={server.today ?? data?.today} />
              <StatRow label="Timezone"    value={server.timezone ?? data?.timezone} />
              <StatRow label="UTC Offset"  value={utcOffset} last />
            </StatusCard>

          </div>

          {/* ── Software ───────────────────────────────────────────────── */}
          <SectionLabel>Software</SectionLabel>
          <div className="grid gap-4 sm:grid-cols-2">
            {updateData && (
              <UpdateCard
                update={updateData}
                onCheckNow={handleCheckNow}
                checking={updateChecking}
              />
            )}
            <ReleaseNotesCard version={version} historyMeta={historyMeta} />
          </div>

          {/* ── Errors ─────────────────────────────────────────────────── */}
          <SectionLabel>Errors</SectionLabel>
          <StatusCard
            title="Recent Errors"
            icon={AlertCircle}
            status={recentErrors.length ? `${recentErrors.length} Open` : 'None'}
            tone={recentErrors.length ? 'bad' : 'good'}
          >
            {recentErrors.length ? (
              recentErrors.slice(0, 5).map((err, i) => (
                <div
                  key={`${err.timestamp ?? err.message ?? i}`}
                  className={cn('py-1.5', i !== Math.min(recentErrors.length, 5) - 1 && 'border-b border-border/40')}
                >
                  <div className="flex items-center justify-between gap-2">
                    <p className="text-xs font-medium leading-tight truncate">
                      {err.source ?? err.type ?? 'Application'}
                    </p>
                    {err.timestamp && (
                      <p className="text-[11px] text-muted-foreground shrink-0 tabular-nums">
                        {formatDateTime(err.timestamp)}
                      </p>
                    )}
                  </div>
                  <p className="text-[11px] text-muted-foreground mt-0.5 line-clamp-1">
                    {err.message ?? String(err)}
                  </p>
                </div>
              ))
            ) : (
              <p className="text-xs text-muted-foreground py-0.5">No recent errors recorded.</p>
            )}
          </StatusCard>

        </>
      )}
    </div>
  );
}
