/**
 * MapTab — world map color threshold configuration editor.
 *
 * Allows the user to set the low / medium / high ban-count thresholds
 * that drive country fill colors on the World Map page.
 */

import { useCallback, useEffect, useMemo, useState } from "react";
import {
  Field,
  Input,
  MessageBar,
  MessageBarBody,
  Skeleton,
  SkeletonItem,
  Text,
  tokens,
} from "@fluentui/react-components";
import { ApiError } from "../../api/client";
import {
  fetchMapColorThresholds,
  updateMapColorThresholds,
} from "../../api/config";
import type { MapColorThresholdsResponse, MapColorThresholdsUpdate } from "../../types/config";
import { useAutoSave } from "../../hooks/useAutoSave";
import { AutoSaveIndicator } from "./AutoSaveIndicator";
import { useConfigStyles } from "./configStyles";

// ---------------------------------------------------------------------------
// Inner form — only mounted after data is loaded.
// ---------------------------------------------------------------------------

interface MapFormProps {
  initial: MapColorThresholdsResponse;
}

function MapForm({ initial }: MapFormProps): React.JSX.Element {
  const styles = useConfigStyles();
  const [thresholdHigh, setThresholdHigh] = useState(String(initial.threshold_high));
  const [thresholdMedium, setThresholdMedium] = useState(String(initial.threshold_medium));
  const [thresholdLow, setThresholdLow] = useState(String(initial.threshold_low));

  const high = Number(thresholdHigh);
  const medium = Number(thresholdMedium);
  const low = Number(thresholdLow);

  const validationError = useMemo<string | null>(() => {
    if (isNaN(high) || isNaN(medium) || isNaN(low))
      return "All thresholds must be valid numbers.";
    if (high <= 0 || medium <= 0 || low <= 0)
      return "All thresholds must be positive integers.";
    if (!(high > medium && medium > low))
      return "Thresholds must satisfy: high > medium > low.";
    return null;
  }, [high, medium, low]);

  // Only pass a new payload to useAutoSave when all values are valid.
  const [validPayload, setValidPayload] = useState<MapColorThresholdsUpdate>({
    threshold_high: initial.threshold_high,
    threshold_medium: initial.threshold_medium,
    threshold_low: initial.threshold_low,
  });

  useEffect(() => {
    if (validationError !== null) return;
    setValidPayload({ threshold_high: high, threshold_medium: medium, threshold_low: low });
  }, [high, medium, low, validationError]);

  const saveThresholds = useCallback(
    async (payload: MapColorThresholdsUpdate): Promise<void> => {
      await updateMapColorThresholds(payload);
    },
    [],
  );

  const { status: saveStatus, errorText: saveErrorText, retry: retrySave } =
    useAutoSave(validPayload, saveThresholds);

  return (
    <div>
      <div className={styles.sectionCard}>
        <Text as="h3" size={500} weight="semibold" block>
          Map Color Thresholds
        </Text>
        <Text
          as="p"
          size={300}
          className={styles.infoText}
          block
          style={{ marginBottom: tokens.spacingVerticalM }}
        >
          Configure the ban count thresholds that determine country fill colors on
          the World Map. Countries with zero bans remain transparent. Colors
          smoothly interpolate between thresholds.
        </Text>

        <div style={{ marginBottom: tokens.spacingVerticalS }}>
          <AutoSaveIndicator
            status={validationError ? "idle" : saveStatus}
            errorText={saveErrorText}
            onRetry={retrySave}
          />
        </div>

        {validationError && (
          <MessageBar intent="error" style={{ marginBottom: tokens.spacingVerticalS }}>
            <MessageBarBody>{validationError}</MessageBarBody>
          </MessageBar>
        )}

        <div className={styles.fieldRowThree}>
          <Field label="Low Threshold (Green)" required>
            <Input
              type="number"
              value={thresholdLow}
              onChange={(_, d) => {
                setThresholdLow(d.value);
              }}
              min={1}
            />
          </Field>
          <Field label="Medium Threshold (Yellow)" required>
            <Input
              type="number"
              value={thresholdMedium}
              onChange={(_, d) => {
                setThresholdMedium(d.value);
              }}
              min={1}
            />
          </Field>
          <Field label="High Threshold (Red)" required>
            <Input
              type="number"
              value={thresholdHigh}
              onChange={(_, d) => {
                setThresholdHigh(d.value);
              }}
              min={1}
            />
          </Field>
        </div>

        <Text
          as="p"
          size={200}
          className={styles.infoText}
          style={{ marginTop: tokens.spacingVerticalS }}
        >
          • 1 to {thresholdLow}: Light green → Full green
          <br />• {thresholdLow} to {thresholdMedium}: Green → Yellow
          <br />• {thresholdMedium} to {thresholdHigh}: Yellow → Red
          <br />• {thresholdHigh}+: Solid red
        </Text>
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Outer loader component.
// ---------------------------------------------------------------------------

/**
 * Tab component for editing world-map ban-count color thresholds.
 *
 * @returns JSX element.
 */
export function MapTab(): React.JSX.Element {
  const [thresholds, setThresholds] = useState<MapColorThresholdsResponse | null>(null);
  const [loadError, setLoadError] = useState<string | null>(null);

  const load = useCallback(async (): Promise<void> => {
    try {
      const data = await fetchMapColorThresholds();
      setThresholds(data);
    } catch (err) {
      setLoadError(
        err instanceof ApiError ? err.message : "Failed to load map color thresholds",
      );
    }
  }, []);

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

  if (!thresholds && !loadError) {
    return (
      <Skeleton aria-label="Loading map settings…">
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 8 }}>
          <SkeletonItem size={32} />
          <SkeletonItem size={32} />
          <SkeletonItem size={32} />
        </div>
      </Skeleton>
    );
  }

  if (loadError)
    return (
      <MessageBar intent="error">
        <MessageBarBody>{loadError}</MessageBarBody>
      </MessageBar>
    );

  if (!thresholds) return <></>;

  return <MapForm initial={thresholds} />;
}


