import { FormEvent, useCallback, useEffect, useState } from "react";
import { Link, useParams } from "react-router-dom";
import {
  getTuleapCredentials,
  getGraylogCredentials,
  listAgents,
  listGraylogDetections,
  listGraylogSubjects,
  manualGraylogPoll,
  setTuleapCredentials,
  setGraylogCredentials,
  testTuleapConnection,
  testGraylogConnection,
} from "../../lib/api";
import { getErrorMessage } from "../../lib/errors";
import type {
  Agent,
  GraylogCredentialsSafe,
  GraylogDetection,
  GraylogSubject,
  TuleapCredentialsSafe,
} from "../../lib/types";
import {
  backLinkClass,
  buttonClass,
  cardContentClass,
  inputClass,
  noticeClass,
  pageStackClass,
  pageTitleClass,
} from "../ui/primitives";

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

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

  const [tuleapUrl, setTuleapUrl] = useState("");
  const [tuleapUsername, setTuleapUsername] = useState("");
  const [tuleapPassword, setTuleapPassword] = useState("");
  const [baseUrl, setBaseUrl] = useState("");
  const [apiToken, setApiToken] = useState("");
  const [analystAgentId, setAnalystAgentId] = useState("");
  const [developerAgentId, setDeveloperAgentId] = useState("");
  const [reviewerAgentId, setReviewerAgentId] = 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 [savingTuleap, setSavingTuleap] = useState(false);
  const [testingTuleap, setTestingTuleap] = 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 reviewers = agents.filter((agent) => agent.role === "reviewer");
  const hasProjectScopedTuleapCredentials =
    Boolean(projectId) && tuleapCredentials?.project_id === projectId;
  const usingGlobalTuleapFallback =
    Boolean(projectId) && Boolean(tuleapCredentials) && tuleapCredentials?.project_id !== projectId;

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

    setLoading(true);
    setError(null);

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

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

      if (tuleapCreds) {
        setTuleapUrl(tuleapCreds.tuleap_url);
        setTuleapUsername(tuleapCreds.username);
      } else {
        setTuleapUrl("");
        setTuleapUsername("");
      }
      setTuleapPassword("");

      if (creds) {
        setBaseUrl(creds.base_url);
        setAnalystAgentId(creds.analyst_agent_id);
        setDeveloperAgentId(creds.developer_agent_id);
        setReviewerAgentId(creds.reviewer_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 handleSaveTuleap(event: FormEvent) {
    event.preventDefault();
    if (!projectId) return;

    setSavingTuleap(true);
    setError(null);
    setSuccess(null);

    try {
      const saved = await setTuleapCredentials(projectId, tuleapUrl, tuleapUsername, tuleapPassword);
      setTuleapCredentialsState(saved);
      setTuleapPassword("");
      setSuccess("Configuration Tuleap sauvegardée.");
    } catch (err: unknown) {
      setError(getErrorMessage(err));
    } finally {
      setSavingTuleap(false);
    }
  }

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

    setTestingTuleap(true);
    setError(null);
    setSuccess(null);

    try {
      const message = await testTuleapConnection(projectId);
      setSuccess(message);
    } catch (err: unknown) {
      setError(getErrorMessage(err));
    } finally {
      setTestingTuleap(false);
    }
  }

  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,
        reviewerAgentId,
        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={pageStackClass}>
      <div>
        {projectId && (
          <Link to={`/projects/${projectId}`} className={backLinkClass}>
            Back
          </Link>
        )}
        <h2 className={pageTitleClass}>Intégrations</h2>
      </div>

      {error && (
        <div className={noticeClass("error")}>
          {error}
        </div>
      )}
      {success && (
        <div className={noticeClass("success")}>
          {success}
        </div>
      )}

      <form onSubmit={handleSaveTuleap} className={`space-y-3 ${cardContentClass}`}>
        <h3 className="text-sm font-semibold text-gray-900">Configuration Tuleap</h3>

        {usingGlobalTuleapFallback && (
          <div className={noticeClass("warning")}>
            Aucun credential Tuleap spécifique au projet n'est configuré. Le fallback global est utilisé.
          </div>
        )}

        <div className="text-xs text-gray-500">
          {hasProjectScopedTuleapCredentials
            ? "Credentials Tuleap projet actifs."
            : "Credentials utilisés pour les trackers Tuleap du projet."}
        </div>

        <input
          className={inputClass}
          type="url"
          value={tuleapUrl}
          onChange={(event) => setTuleapUrl(event.target.value)}
          placeholder="https://tuleap.example.com"
          required
        />

        <input
          className={inputClass}
          type="text"
          value={tuleapUsername}
          onChange={(event) => setTuleapUsername(event.target.value)}
          placeholder="Username Tuleap"
          required
        />

        <input
          className={inputClass}
          type="password"
          value={tuleapPassword}
          onChange={(event) => setTuleapPassword(event.target.value)}
          placeholder="Mot de passe Tuleap"
          required
        />

        <div className="flex gap-2">
          <button
            type="submit"
            disabled={savingTuleap}
            className={buttonClass({ variant: "primary" })}
          >
            {savingTuleap ? "Sauvegarde..." : "Sauvegarder"}
          </button>
          <button
            type="button"
            onClick={() => void handleTestTuleap()}
            disabled={testingTuleap || !tuleapCredentials}
            className={buttonClass({ variant: "secondary" })}
          >
            {testingTuleap ? "Test..." : "Tester la connexion"}
          </button>
        </div>
      </form>

      <form onSubmit={handleSave} className={`space-y-3 ${cardContentClass}`}>
        <h3 className="text-sm font-semibold text-gray-900">Configuration Graylog</h3>

        <input
          className={inputClass}
          value={baseUrl}
          onChange={(event) => setBaseUrl(event.target.value)}
          placeholder="https://graylog.example.com"
          required
        />

        <input
          className={inputClass}
          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-3">
          <select
            className={inputClass}
            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={inputClass}
            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>
          <select
            className={inputClass}
            value={reviewerAgentId}
            onChange={(event) => setReviewerAgentId(event.target.value)}
            required
          >
            <option value="">Reviewer agent</option>
            {reviewers.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={inputClass}
            value={streamId}
            onChange={(event) => setStreamId(event.target.value)}
            placeholder="stream_id (optionnel)"
          />
          <input
            className={`${inputClass} 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={inputClass}
            value={pollingIntervalMinutes}
            onChange={(event) => setPollingIntervalMinutes(Number(event.target.value))}
            min={1}
          />
          <input
            type="number"
            className={inputClass}
            value={lookbackMinutes}
            onChange={(event) => setLookbackMinutes(Number(event.target.value))}
            min={1}
          />
          <input
            type="number"
            className={inputClass}
            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={buttonClass({ variant: "primary" })}
          >
            {saving ? "Sauvegarde..." : "Sauvegarder"}
          </button>
          <button
            type="button"
            onClick={() => void handleTestConnection()}
            className={buttonClass({ variant: "secondary" })}
          >
            Tester la connexion
          </button>
          <button
            type="button"
            onClick={() => void handleManualPoll()}
            className={buttonClass({ variant: "neutralDark" })}
          >
            Poll manuel
          </button>
        </div>
      </form>

      <div className={cardContentClass}>
        <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={cardContentClass}>
        <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>
  );
}
