import React, { useEffect, useRef, useState } from "react";
import { apiFetch } from "../api";
import { useAuth } from "../state";

const PAGE_SIZE = 10;

function scoreQuery(row) {
  const mean = Number(row.mean_time || 0);
  const calls = Number(row.calls || 0);
  const total = Number(row.total_time || 0);
  const rows = Number(row.rows || 0);
  return mean * 1.4 + total * 0.9 + calls * 0.2 + Math.min(rows / 50, 25);
}

function classifyQuery(row) {
  if ((row.mean_time || 0) > 100) return { label: "Very Slow", kind: "danger" };
  if ((row.total_time || 0) > 250) return { label: "Heavy", kind: "warn" };
  if ((row.calls || 0) > 500) return { label: "Frequent", kind: "info" };
  return { label: "Normal", kind: "ok" };
}

function compactSql(sql) {
  if (!sql) return "-";
  return sql.replace(/\s+/g, " ").trim();
}

function buildQueryTips(row) {
  if (!row) return [];
  const tips = [];
  const sql = (row.query_text || "").toLowerCase();

  if ((row.mean_time || 0) > 100) {
    tips.push("High latency per call: inspect execution plan with EXPLAIN (ANALYZE, BUFFERS).");
  }
  if ((row.total_time || 0) > 500) {
    tips.push("High cumulative runtime: optimize this query first for fastest overall impact.");
  }
  if ((row.calls || 0) > 500) {
    tips.push("Very frequent query: consider caching or reducing call frequency in application code.");
  }
  if ((row.rows || 0) > 100000) {
    tips.push("Large row output: return fewer columns/rows or add pagination at query/API layer.");
  }
  if (/select\s+\*/.test(sql)) {
    tips.push("Avoid SELECT *: request only required columns to reduce IO and transfer cost.");
  }
  if (/order\s+by/.test(sql) && !/limit\s+\d+/.test(sql)) {
    tips.push("ORDER BY without LIMIT can be expensive: add LIMIT where possible.");
  }
  if (/where/.test(sql) && / from /.test(sql)) {
    tips.push("Filter query detected: verify indexes exist on WHERE / JOIN columns.");
  }
  if (/like\s+'%/.test(sql)) {
    tips.push("Leading wildcard LIKE can bypass indexes: consider trigram index (pg_trgm).");
  }
  if (tips.length === 0) {
    tips.push("No obvious anti-pattern detected. Validate with EXPLAIN and index usage statistics.");
  }

  return tips.slice(0, 5);
}

export function QueryInsightsPage() {
  const { tokens, refresh } = useAuth();
  const refreshRef = useRef(refresh);
  const [targets, setTargets] = useState([]);
  const [targetId, setTargetId] = useState("");
  const [rows, setRows] = useState([]);
  const [selectedQuery, setSelectedQuery] = useState(null);
  const [search, setSearch] = useState("");
  const [page, setPage] = useState(1);
  const [error, setError] = useState("");
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    refreshRef.current = refresh;
  }, [refresh]);

  useEffect(() => {
    (async () => {
      try {
        const t = await apiFetch("/targets", {}, tokens, refresh);
        const supported = t.filter((item) => item.use_pg_stat_statements !== false);
        setTargets(supported);
        if (supported.length > 0) setTargetId(String(supported[0].id));
        else setTargetId("");
      } catch (e) {
        setError(String(e.message || e));
      } finally {
        setLoading(false);
      }
    })();
  }, []);

  useEffect(() => {
    if (!targetId) return;
    let active = true;
    (async () => {
      try {
        const data = await apiFetch(`/targets/${targetId}/top-queries`, {}, tokens, refreshRef.current);
        if (!active) return;
        setRows(data);
        setSelectedQuery((prev) => {
          if (!prev) return data[0] || null;
          const keep = data.find((row) => row.queryid === prev.queryid);
          return keep || data[0] || null;
        });
        setPage((prev) => (prev === 1 ? prev : 1));
      } catch (e) {
        if (active) setError(String(e.message || e));
      }
    })();
    return () => {
      active = false;
    };
  }, [targetId, tokens?.accessToken, tokens?.refreshToken]);

  const dedupedByQueryId = [...rows].reduce((acc, row) => {
    if (!row?.queryid) return acc;
    if (!acc[row.queryid]) acc[row.queryid] = row;
    return acc;
  }, {});
  const uniqueRows = Object.values(dedupedByQueryId);

  const sorted = [...uniqueRows].sort((a, b) => (b.total_time || 0) - (a.total_time || 0));
  const byMean = [...uniqueRows].sort((a, b) => (b.mean_time || 0) - (a.mean_time || 0));
  const byCalls = [...uniqueRows].sort((a, b) => (b.calls || 0) - (a.calls || 0));
  const byRows = [...uniqueRows].sort((a, b) => (b.rows || 0) - (a.rows || 0));
  const byPriority = [...uniqueRows].sort((a, b) => scoreQuery(b) - scoreQuery(a));

  const filtered = byPriority.filter((r) => {
    if (!search.trim()) return true;
    return compactSql(r.query_text).toLowerCase().includes(search.toLowerCase());
  });
  const totalPages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
  const safePage = Math.min(page, totalPages);
  const paged = filtered.slice((safePage - 1) * PAGE_SIZE, safePage * PAGE_SIZE);
  const selectedTips = buildQueryTips(selectedQuery);

  const categories = [
    { key: "priority", title: "Optimization Priority", row: byPriority[0], subtitle: "Best first candidate to optimize" },
    { key: "total", title: "Longest Total Time", row: sorted[0], subtitle: "Biggest cumulative runtime impact" },
    { key: "mean", title: "Highest Mean Time", row: byMean[0], subtitle: "Slowest single-call latency" },
    { key: "calls", title: "Most Frequent", row: byCalls[0], subtitle: "Executed very often" },
    { key: "rows", title: "Most Rows Returned", row: byRows[0], subtitle: "Potentially heavy scans" },
  ];

  return (
    <div className="query-insights-page">
      <h2>Query Insights</h2>
      <p>Note: This section requires the <code>pg_stat_statements</code> extension on the monitored target.</p>
      {targets.length === 0 && !loading && (
        <div className="card">
          No targets with enabled <code>pg_stat_statements</code> are available.
          Enable it in <strong>Targets Management</strong> for a target to use Query Insights.
        </div>
      )}
      {error && <div className="card error">{error}</div>}
      <div className="card query-toolbar">
        <div className="field">
          <label>Target</label>
          <select value={targetId} onChange={(e) => setTargetId(e.target.value)} disabled={!targets.length}>
            {targets.map((t) => (
              <option key={t.id} value={t.id}>
                {t.name}
              </option>
            ))}
          </select>
        </div>
        <div className="field">
          <label>Search Query Text</label>
          <input
            value={search}
            onChange={(e) => {
              setSearch(e.target.value);
              setPage(1);
            }}
            placeholder="e.g. select * from users"
          />
        </div>
      </div>

      {loading ? (
        <div className="card">Loading query insights...</div>
      ) : (
        <>
          <div className="grid three">
            {categories.map((item) => {
              const r = item.row;
              const state = r ? classifyQuery(r) : null;
              return (
                <div
                  className="card query-category"
                  key={item.key}
                  onClick={() => r && setSelectedQuery(r)}
                  role="button"
                  tabIndex={0}
                >
                  <h4>{item.title}</h4>
                  <small>{item.subtitle}</small>
                  {r ? (
                    <>
                      <div className={`query-state ${state.kind}`}>{state.label}</div>
                      <div className="query-kpi">
                        <span>Total</span>
                        <strong>{Number(r.total_time || 0).toFixed(2)} ms</strong>
                      </div>
                      <div className="query-kpi">
                        <span>Mean</span>
                        <strong>{Number(r.mean_time || 0).toFixed(2)} ms</strong>
                      </div>
                      <div className="query-kpi">
                        <span>Calls</span>
                        <strong>{r.calls}</strong>
                      </div>
                    </>
                  ) : (
                    <p>No data</p>
                  )}
                </div>
              );
            })}
          </div>

          <div className="grid two">
            <div className="card query-list">
              <h3>Ranked Queries</h3>
              <table>
                <thead>
                  <tr>
                    <th>Priority</th>
                    <th>Calls</th>
                    <th>Total ms</th>
                    <th>Mean ms</th>
                    <th>Rows</th>
                    <th>Query Preview</th>
                  </tr>
                </thead>
                <tbody>
                  {paged.map((r, i) => {
                    const state = classifyQuery(r);
                    return (
                      <tr key={`${r.queryid}-${i}-${safePage}`} className={selectedQuery?.queryid === r.queryid ? "active-row" : ""}>
                        <td><span className={`query-state ${state.kind}`}>{state.label}</span></td>
                        <td>{r.calls}</td>
                        <td>{Number(r.total_time || 0).toFixed(2)}</td>
                        <td>{Number(r.mean_time || 0).toFixed(2)}</td>
                        <td>{r.rows}</td>
                        <td className="query">
                          <button className="table-link" onClick={() => setSelectedQuery(r)}>
                            {compactSql(r.query_text)}
                          </button>
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
              <div className="pagination">
                <span className="pagination-info">
                  Showing {paged.length} of {filtered.length} queries
                </span>
                <div className="pagination-actions">
                  <button type="button" disabled={safePage <= 1} onClick={() => setPage((p) => Math.max(1, p - 1))}>
                    Prev
                  </button>
                  <span>Page {safePage} / {totalPages}</span>
                  <button type="button" disabled={safePage >= totalPages} onClick={() => setPage((p) => Math.min(totalPages, p + 1))}>
                    Next
                  </button>
                </div>
              </div>
            </div>

            <div className="card query-detail">
              <h3>Selected Query</h3>
              {selectedQuery ? (
                <>
                  <div className="overview-metrics">
                    <div><span>Calls</span><strong>{selectedQuery.calls}</strong></div>
                    <div><span>Total Time</span><strong>{Number(selectedQuery.total_time || 0).toFixed(2)} ms</strong></div>
                    <div><span>Mean Time</span><strong>{Number(selectedQuery.mean_time || 0).toFixed(2)} ms</strong></div>
                    <div><span>Rows</span><strong>{selectedQuery.rows}</strong></div>
                  </div>
                  <div className="sql-block">
                    <code>{selectedQuery.query_text || "-- no query text available --"}</code>
                  </div>
                  <div className="query-tips">
                    <h4>Optimization Suggestions</h4>
                    <ul>
                      {selectedTips.map((tip, idx) => <li key={idx}>{tip}</li>)}
                    </ul>
                  </div>
                  <p className="query-hint">
                    Tip: focus first on queries with high <strong>Total Time</strong> (overall impact) and high <strong>Mean Time</strong> (latency hotspots).
                  </p>
                </>
              ) : (
                <p>No query selected.</p>
              )}
            </div>
          </div>
        </>
      )}
    </div>
  );
}
