import { FormEvent, useCallback, useEffect, useState } from "react";
import { Link, useParams } from "react-router-dom";
import {
  getGraylogCredentials,
  listAgents,
  listGraylogDetections,
  listGraylogSubjects,
  manualGraylogPoll,
  setGraylogCredentials,
  testGraylogConnection,
} from "../../lib/api";
import { getErrorMessage } from "../../lib/errors";
import type {
  Agent,
  GraylogCredentialsSafe,
  GraylogDetection,
  GraylogSubject,
} from "../../lib/types";

export default function ProjectGraylog() {
  const { projectId } = useParams<{ projectId: string }>();

  const [agents, setAgents] = useState<Agent[]>([]);
  const [credentials, setCredentials] = useState<GraylogCredentialsSafe | null>(null);
  const [subjects, setSubjects] = useState<GraylogSubject[]>([]);
  const [detections, setDetections] = useState<GraylogDetection[]>([]);

  const [baseUrl, setBaseUrl] = useState("");
  const [apiToken, setApiToken] = useState("");
  const [analystAgentId, setAnalystAgentId] = useState("");
  const [developerAgentId, setDeveloperAgentId] = useState("");
  const [streamId, setStreamId] = useState("");
  const [queryFilter, setQueryFilter] = useState("level:(critical OR error OR warning)");
  const [pollingIntervalMinutes, setPollingIntervalMinutes] = useState(10);
  const [lookbackMinutes, setLookbackMinutes] = useState(30);
  const [scoreThreshold, setScoreThreshold] = useState(70);

  const [loading, setLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [success, setSuccess] = useState<string | null>(null);

  const analysts = agents.filter((agent) => agent.role === "analyst");
  const developers = agents.filter((agent) => agent.role === "developer");

  const refresh = useCallback(async () => {
    if (!projectId) return;

    setLoading(true);
    setError(null);

    try {
      const [agentList, creds, subjectList, detectionList] = await Promise.all([
        listAgents(),
        getGraylogCredentials(projectId),
        listGraylogSubjects(projectId),
        listGraylogDetections(projectId),
      ]);

      setAgents(agentList);
      setCredentials(creds);
      setSubjects(subjectList);
      setDetections(detectionList);

      if (creds) {
        setBaseUrl(creds.base_url);
        setAnalystAgentId(creds.analyst_agent_id);
        setDeveloperAgentId(creds.developer_agent_id);
        setStreamId(creds.stream_id ?? "");
        setQueryFilter(creds.query_filter);
        setPollingIntervalMinutes(creds.polling_interval_minutes);
        setLookbackMinutes(creds.lookback_minutes);
        setScoreThreshold(creds.score_threshold);
      }
    } catch (err: unknown) {
      setError(getErrorMessage(err));
    } finally {
      setLoading(false);
    }
  }, [projectId]);

  useEffect(() => {
    void refresh();
  }, [refresh]);

  async function handleSave(event: FormEvent) {
    event.preventDefault();
    if (!projectId) return;

    setSaving(true);
    setError(null);
    setSuccess(null);

    try {
      const saved = await setGraylogCredentials(
        projectId,
        baseUrl,
        apiToken,
        analystAgentId,
        developerAgentId,
        streamId.trim() || null,
        queryFilter,
        pollingIntervalMinutes,
        lookbackMinutes,
        scoreThreshold
      );

      setCredentials(saved);
      setApiToken("");
      setSuccess("Configuration Graylog sauvegardée.");
      await refresh();
    } catch (err: unknown) {
      setError(getErrorMessage(err));
    } finally {
      setSaving(false);
    }
  }

  async function handleTestConnection() {
    if (!projectId) return;

    setError(null);
    setSuccess(null);

    try {
      const message = await testGraylogConnection(projectId);
      setSuccess(message);
    } catch (err: unknown) {
      setError(getErrorMessage(err));
    }
  }

  async function handleManualPoll() {
    if (!projectId) return;

    setError(null);
    setSuccess(null);

    try {
      const triggeredCount = await manualGraylogPoll(projectId);
      setSuccess(`Polling Graylog manuel terminé: ${triggeredCount} sujet(s) déclenché(s).`);
      await refresh();
    } catch (err: unknown) {
      setError(getErrorMessage(err));
    }
  }

  return (
    <div className="space-y-6 p-8">
      <div>
        {projectId && (
          <Link to={`/projects/${projectId}`} className="mb-1 inline-flex text-sm text-blue-600 hover:underline">
            Back
          </Link>
        )}
        <h2 className="text-xl font-bold">Graylog</h2>
      </div>

      {error && (
        <div className="rounded border border-red-200 bg-red-50 p-3 text-sm text-red-700">
          {error}
        </div>
      )}
      {success && (
        <div className="rounded border border-green-200 bg-green-50 p-3 text-sm text-green-700">
          {success}
        </div>
      )}

      <form
        onSubmit={handleSave}
        className="space-y-3 rounded-lg border border-gray-200 bg-white p-4"
      >
        <h3 className="text-sm font-semibold text-gray-900">Configuration</h3>

        <input
          className="w-full rounded border border-gray-300 px-3 py-2 text-sm"
          value={baseUrl}
          onChange={(event) => setBaseUrl(event.target.value)}
          placeholder="https://graylog.example.com"
          required
        />

        <input
          className="w-full rounded border border-gray-300 px-3 py-2 text-sm"
          value={apiToken}
          onChange={(event) => setApiToken(event.target.value)}
          placeholder={
            credentials
              ? "Laisser vide pour conserver le token actuel"
              : "Token API Graylog"
          }
          required={!credentials}
        />

        <div className="grid gap-3 md:grid-cols-2">
          <select
            className="rounded border border-gray-300 px-3 py-2 text-sm"
            value={analystAgentId}
            onChange={(event) => setAnalystAgentId(event.target.value)}
            required
          >
            <option value="">Analyst agent</option>
            {analysts.map((agent) => (
              <option key={agent.id} value={agent.id}>
                {agent.name}
              </option>
            ))}
          </select>

          <select
            className="rounded border border-gray-300 px-3 py-2 text-sm"
            value={developerAgentId}
            onChange={(event) => setDeveloperAgentId(event.target.value)}
            required
          >
            <option value="">Developer agent</option>
            {developers.map((agent) => (
              <option key={agent.id} value={agent.id}>
                {agent.name}
              </option>
            ))}
          </select>
        </div>

        <div className="grid gap-3 md:grid-cols-4">
          <input
            className="rounded border border-gray-300 px-3 py-2 text-sm"
            value={streamId}
            onChange={(event) => setStreamId(event.target.value)}
            placeholder="stream_id (optionnel)"
          />
          <input
            className="rounded border border-gray-300 px-3 py-2 text-sm md:col-span-3"
            value={queryFilter}
            onChange={(event) => setQueryFilter(event.target.value)}
            placeholder="Filtre query Graylog"
          />
        </div>

        <div className="grid gap-3 md:grid-cols-3">
          <input
            type="number"
            className="rounded border border-gray-300 px-3 py-2 text-sm"
            value={pollingIntervalMinutes}
            onChange={(event) => setPollingIntervalMinutes(Number(event.target.value))}
            min={1}
          />
          <input
            type="number"
            className="rounded border border-gray-300 px-3 py-2 text-sm"
            value={lookbackMinutes}
            onChange={(event) => setLookbackMinutes(Number(event.target.value))}
            min={1}
          />
          <input
            type="number"
            className="rounded border border-gray-300 px-3 py-2 text-sm"
            value={scoreThreshold}
            onChange={(event) => setScoreThreshold(Number(event.target.value))}
            min={1}
            max={100}
          />
        </div>

        <div className="flex gap-2">
          <button
            type="submit"
            disabled={saving}
            className="rounded bg-blue-600 px-4 py-2 text-sm text-white hover:bg-blue-700 disabled:opacity-50"
          >
            {saving ? "Sauvegarde..." : "Sauvegarder"}
          </button>
          <button
            type="button"
            onClick={() => void handleTestConnection()}
            className="rounded bg-gray-200 px-4 py-2 text-sm text-gray-800 hover:bg-gray-300"
          >
            Tester la connexion
          </button>
          <button
            type="button"
            onClick={() => void handleManualPoll()}
            className="rounded bg-gray-900 px-4 py-2 text-sm text-white hover:bg-black"
          >
            Poll manuel
          </button>
        </div>
      </form>

      <div className="rounded-lg border border-gray-200 bg-white p-4">
        <h3 className="mb-3 text-sm font-semibold text-gray-900">Sujets détectés</h3>

        {loading ? (
          <div className="text-sm text-gray-500">Chargement...</div>
        ) : subjects.length === 0 ? (
          <div className="text-sm text-gray-400">Aucun sujet détecté.</div>
        ) : (
          <div className="space-y-2">
            {subjects.map((subject) => (
              <div key={subject.id} className="rounded border border-gray-100 p-3">
                <div className="text-sm font-medium text-gray-900">{subject.source}</div>
                <div className="text-xs text-gray-600">{subject.normalized_message}</div>
                <div className="mt-1 text-xs text-gray-500">
                  Score: {subject.last_score} | Statut: {subject.status} | Last seen: {" "}
                  {new Date(subject.last_seen_at).toLocaleString()}
                </div>
              </div>
            ))}
          </div>
        )}
      </div>

      <div className="rounded-lg border border-gray-200 bg-white p-4">
        <h3 className="mb-3 text-sm font-semibold text-gray-900">Dernières détections</h3>

        {detections.length === 0 ? (
          <div className="text-sm text-gray-400">Aucune détection enregistrée.</div>
        ) : (
          <div className="space-y-2">
            {detections.slice(0, 20).map((detection) => (
              <div
                key={detection.id}
                className="rounded border border-gray-100 p-3 text-xs text-gray-700"
              >
                score={detection.score} total={detection.total_count} triggered={" "}
                {String(detection.triggered)} at={" "}
                {new Date(detection.created_at).toLocaleString()}
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}
