import React, { useEffect, useMemo, useState } from "react";
import { useParams } from "react-router-dom";
import { Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts";
import { apiFetch } from "../api";
import { useAuth } from "../state";

const ranges = {
  "15m": 15 * 60 * 1000,
  "1h": 60 * 60 * 1000,
  "24h": 24 * 60 * 60 * 1000,
  "7d": 7 * 24 * 60 * 60 * 1000,
};

function toQueryRange(range) {
  const to = new Date();
  const from = new Date(to.getTime() - ranges[range]);
  return { from: from.toISOString(), to: to.toISOString() };
}

function formatBytes(value) {
  if (value === null || value === undefined) return "-";
  const units = ["B", "KB", "MB", "GB", "TB"];
  let n = Number(value);
  let i = 0;
  while (n >= 1024 && i < units.length - 1) {
    n /= 1024;
    i += 1;
  }
  return `${n.toFixed(i >= 2 ? 2 : 0)} ${units[i]}`;
}

function formatSeconds(value) {
  if (value === null || value === undefined) return "-";
  if (value < 60) return `${value.toFixed(1)}s`;
  if (value < 3600) return `${(value / 60).toFixed(1)}m`;
  return `${(value / 3600).toFixed(1)}h`;
}

function formatNumber(value, digits = 2) {
  if (value === null || value === undefined || Number.isNaN(Number(value))) return "-";
  return Number(value).toFixed(digits);
}

function MetricsTooltip({ active, payload, label }) {
  if (!active || !payload || payload.length === 0) return null;
  const row = payload[0]?.payload || {};
  return (
    <div className="chart-tooltip">
      <div className="chart-tooltip-time">{label}</div>
      <div className="chart-tooltip-item c1">connections: {formatNumber(row.connections, 0)}</div>
      <div className="chart-tooltip-item c2">tps: {formatNumber(row.tps, 2)}</div>
      <div className="chart-tooltip-item c3">cache: {formatNumber(row.cache, 2)}%</div>
    </div>
  );
}

async function loadMetric(targetId, metric, range, tokens, refresh) {
  const { from, to } = toQueryRange(range);
  return apiFetch(
    `/targets/${targetId}/metrics?metric=${encodeURIComponent(metric)}&from=${encodeURIComponent(from)}&to=${encodeURIComponent(to)}`,
    {},
    tokens,
    refresh
  );
}

export function TargetDetailPage() {
  const { id } = useParams();
  const { tokens, refresh } = useAuth();
  const [range, setRange] = useState("1h");
  const [series, setSeries] = useState({});
  const [locks, setLocks] = useState([]);
  const [activity, setActivity] = useState([]);
  const [overview, setOverview] = useState(null);
  const [targetMeta, setTargetMeta] = useState(null);
  const [error, setError] = useState("");
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let active = true;
    (async () => {
      setLoading(true);
      try {
        const [connections, xacts, cache, locksTable, activityTable, overviewData, targetInfo] = await Promise.all([
          loadMetric(id, "connections_total", range, tokens, refresh),
          loadMetric(id, "xacts_total", range, tokens, refresh),
          loadMetric(id, "cache_hit_ratio", range, tokens, refresh),
          apiFetch(`/targets/${id}/locks`, {}, tokens, refresh),
          apiFetch(`/targets/${id}/activity`, {}, tokens, refresh),
          apiFetch(`/targets/${id}/overview`, {}, tokens, refresh),
          apiFetch(`/targets/${id}`, {}, tokens, refresh),
        ]);
        if (!active) return;
        setSeries({ connections, xacts, cache });
        setLocks(locksTable);
        setActivity(activityTable);
        setOverview(overviewData);
        setTargetMeta(targetInfo);
        setError("");
      } catch (e) {
        if (active) setError(String(e.message || e));
      } finally {
        if (active) setLoading(false);
      }
    })();
    return () => {
      active = false;
    };
  }, [id, range, tokens, refresh]);

  const chartData = useMemo(
    () => {
      const con = series.connections || [];
      const xacts = series.xacts || [];
      const cache = series.cache || [];
      return con.map((point, idx) => {
        const prev = xacts[idx - 1];
        const curr = xacts[idx];
        let tps = 0;
        if (prev && curr) {
          const dt = (new Date(curr.ts).getTime() - new Date(prev.ts).getTime()) / 1000;
          const dx = (curr.value || 0) - (prev.value || 0);
          if (dt > 0 && dx >= 0) {
            tps = dx / dt;
          }
        }
        return {
          ts: new Date(point.ts).toLocaleTimeString(),
          connections: point.value,
          tps,
          cache: (cache[idx]?.value || 0) * 100,
        };
      });
    },
    [series]
  );

  if (loading) return <div className="card">Loading target detail...</div>;
  if (error) return <div className="card error">{error}</div>;

  const role = overview?.instance?.role || "-";
  const isPrimary = role === "primary";
  const isStandby = role === "standby";

  return (
    <div>
      <h2>
        Target Detail {targetMeta?.name || `#${id}`}
        {targetMeta?.dbname ? ` (${targetMeta.dbname})` : ""}
      </h2>
      {overview && (
        <div className="card">
          <h3>Database Overview</h3>
          <div className="grid three overview-kv">
            <div><span>PostgreSQL Version</span><strong>{overview.instance.server_version || "-"}</strong></div>
            <div>
              <span>Role</span>
              <strong className={isPrimary ? "pill primary" : isStandby ? "pill standby" : "pill"}>{role}</strong>
            </div>
            <div title="Time since PostgreSQL postmaster start">
              <span>Uptime</span><strong>{formatSeconds(overview.instance.uptime_seconds)}</strong>
            </div>
            <div><span>Database</span><strong>{overview.instance.current_database || "-"}</strong></div>
            <div>
              <span>Target Port</span>
              <strong>{targetMeta?.port ?? "-"}</strong>
            </div>
            <div title="Current database total size">
              <span>Current DB Size</span><strong>{formatBytes(overview.storage.current_database_size_bytes)}</strong>
            </div>
            <div title="Total WAL directory size (when available)">
              <span>WAL Size</span><strong>{formatBytes(overview.storage.wal_directory_size_bytes)}</strong>
            </div>
            <div title="Optional metric via future Agent/SSH provider">
              <span>Free Disk</span><strong>{formatBytes(overview.storage.disk_space.free_bytes)}</strong>
            </div>
            <div title="Replication replay delay on standby">
              <span>Replay Lag</span>
              <strong className={overview.replication.replay_lag_seconds > 5 ? "lag-bad" : ""}>
                {formatSeconds(overview.replication.replay_lag_seconds)}
              </strong>
            </div>
            <div><span>Replication Slots</span><strong>{overview.replication.replication_slots_count ?? "-"}</strong></div>
            <div><span>Repl Clients</span><strong>{overview.replication.active_replication_clients ?? "-"}</strong></div>
            <div><span>Autovacuum Workers</span><strong>{overview.performance.autovacuum_workers ?? "-"}</strong></div>
          </div>

          <div className="grid two">
            <div>
              <h4>Size all databases</h4>
              <table>
                <thead><tr><th>Database</th><th>Size</th></tr></thead>
                <tbody>
                  {(overview.storage.all_databases || []).map((d) => (
                    <tr key={d.name}><td>{d.name}</td><td>{formatBytes(d.size_bytes)}</td></tr>
                  ))}
                </tbody>
              </table>
            </div>
            <div>
              <h4>Largest Tables (Top 5)</h4>
              <table>
                <thead><tr><th>Table</th><th>Size</th></tr></thead>
                <tbody>
                  {(overview.storage.largest_tables || []).map((t, i) => (
                    <tr key={`${t.schema}.${t.table}.${i}`}><td>{t.schema}.{t.table}</td><td>{formatBytes(t.size_bytes)}</td></tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>

          <div className="grid two">
            <div>
              <h4>Replication Clients</h4>
              <table>
                <thead><tr><th>Client</th><th>State</th><th>Lag</th></tr></thead>
                <tbody>
                  {(overview.replication.clients || []).map((c, i) => (
                    <tr key={`${c.client_addr || "n/a"}-${i}`}>
                      <td>{c.client_addr || c.application_name || "-"}</td>
                      <td>{c.state || "-"}</td>
                      <td className={(c.replay_lag_seconds || 0) > 5 ? "lag-bad" : ""}>
                        {c.replay_lag_seconds != null ? formatSeconds(c.replay_lag_seconds) : formatBytes(c.replay_lag_bytes)}
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
            <div>
              <h4>Performance Core Metrics</h4>
              <div className="overview-metrics">
                <div><span>xact_commit</span><strong>{overview.performance.xact_commit ?? "-"}</strong></div>
                <div><span>xact_rollback</span><strong>{overview.performance.xact_rollback ?? "-"}</strong></div>
                <div><span>deadlocks</span><strong>{overview.performance.deadlocks ?? "-"}</strong></div>
                <div><span>temp_files</span><strong>{overview.performance.temp_files ?? "-"}</strong></div>
                <div><span>temp_bytes</span><strong>{formatBytes(overview.performance.temp_bytes)}</strong></div>
                <div><span>blk_read_time</span><strong>{overview.performance.blk_read_time ?? "-"} ms</strong></div>
                <div><span>blk_write_time</span><strong>{overview.performance.blk_write_time ?? "-"} ms</strong></div>
                <div><span>checkpoints_timed</span><strong>{overview.performance.checkpoints_timed ?? "-"}</strong></div>
                <div><span>checkpoints_req</span><strong>{overview.performance.checkpoints_req ?? "-"}</strong></div>
              </div>
            </div>
          </div>

          {overview.partial_failures?.length > 0 && (
            <div className="partial-warning">
              <strong>Partial data warnings:</strong>
              <ul>
                {overview.partial_failures.map((w, i) => <li key={i}>{w}</li>)}
              </ul>
            </div>
          )}
        </div>
      )}
      <div className="range-picker">
        {Object.keys(ranges).map((r) => (
          <button key={r} onClick={() => setRange(r)} className={r === range ? "active" : ""}>
            {r}
          </button>
        ))}
      </div>
      <div className="card" style={{ height: 320 }}>
        <h3>Connections / TPS (approx) / Cache Hit Ratio</h3>
        <ResponsiveContainer width="100%" height="85%">
          <LineChart data={chartData}>
            <XAxis dataKey="ts" hide />
            <YAxis yAxisId="left" />
            <YAxis yAxisId="right" orientation="right" domain={[0, 100]} />
            <Tooltip content={<MetricsTooltip />} />
            <Line yAxisId="left" type="monotone" dataKey="connections" stroke="#38bdf8" dot={false} strokeWidth={2} />
            <Line yAxisId="left" type="monotone" dataKey="tps" stroke="#22c55e" dot={false} strokeWidth={2} />
            <Line yAxisId="right" type="monotone" dataKey="cache" stroke="#f59e0b" dot={false} strokeWidth={2} />
          </LineChart>
        </ResponsiveContainer>
      </div>
      <div className="grid two">
        <div className="card">
          <h3>Locks</h3>
          <table>
            <thead>
              <tr>
                <th>Type</th>
                <th>Mode</th>
                <th>Granted</th>
                <th>Relation</th>
                <th>PID</th>
              </tr>
            </thead>
            <tbody>
              {locks.map((l, i) => (
                <tr key={i}>
                  <td>{l.locktype}</td>
                  <td>{l.mode}</td>
                  <td>{String(l.granted)}</td>
                  <td>{l.relation || "-"}</td>
                  <td>{l.pid}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div className="card">
          <h3>Activity</h3>
          <table>
            <thead>
              <tr>
                <th>PID</th>
                <th>User</th>
                <th>State</th>
                <th>Wait</th>
              </tr>
            </thead>
            <tbody>
              {activity.map((a) => (
                <tr key={a.pid}>
                  <td>{a.pid}</td>
                  <td>{a.usename}</td>
                  <td>{a.state}</td>
                  <td>{a.wait_event_type || "-"}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}
