"use client";

/**
 * Smartsheet Integration — `/admin/water-log/settings` section.
 *
 * Self-contained card that lets a brand admin configure the Smartsheet
 * integration for their Water Log entries:
 *
 *   1. Enable/disable the integration
 *   2. Smartsheet sheet URL or numeric sheet ID
 *   3. API token (password field; never sent back to the client after save)
 *   4. Sync frequency (realtime / every 15 minutes / hourly)
 *   5. Column mapping (entry_id, logged_at, headgate, measurement,
 *      unit, irrigator, notes)
 *   6. Test Connection button — fetches sheet metadata so the column
 *      dropdowns are populated
 *   7. Recent Activity panel — last 10 sync attempts (green ✓ / red ✗)
 *
 * Visual language matches the parent Water Log settings page
 * (cream + forest palette, "Field Almanac" style).
 *
 * Threading brandId:
 *   The card takes `brandId` as a prop per CLAUDE.md ("Brand ID
 *   Threading"). The current Water Log settings page still hardcodes
 *   TUXEDO_BRAND_ID; this card accepts it as a prop so the page can
 *   be lifted later without rewrites.
 */

import { useEffect, useReducer, useCallback } from "react";
import {
  getSmartsheetConfig,
  saveSmartsheetConfig,
  testSmartsheetConnection,
  listSmartsheetSyncLog,
  type SmartsheetConfigResponse,
  type SmartsheetSyncLogEntry,
} from "@/actions/water-log/smartsheet";
import type {
  SmartsheetColumnMapping,
  SmartsheetFrequency,
} from "@/db/schema/water-log";
import { formatDateTime } from "@/lib/format-date";

const COLUMN_LABELS: Record<keyof SmartsheetColumnMapping, string> = {
  entry_id: "Entry ID (UUID, for dedup)",
  logged_at: "Logged at (timestamp)",
  headgate: "Headgate name",
  measurement: "Measurement",
  unit: "Unit (CFS, GPM, …)",
  irrigator: "Irrigator name",
  notes: "Notes (optional)",
};

const REQUIRED_COLUMNS: (keyof SmartsheetColumnMapping)[] = [
  "entry_id",
  "logged_at",
];

const FREQUENCY_LABELS: Record<SmartsheetFrequency, string> = {
  realtime: "Real-time (after every entry)",
  every_15_minutes: "Every 15 minutes",
  hourly: "Hourly",
};

type ColumnOption = { id: string; title: string; type: string };

type TestState =
  | { state: "idle" }
  | { state: "loading" }
  | {
      state: "ok";
      sheetName: string;
      columnCount: number;
      columns: ColumnOption[];
    }
  | { state: "error"; message: string };

type State = {
  loading: boolean;
  saving: boolean;
  message: { type: "success" | "error"; text: string } | null;
  // Persisted (saved) values — for displaying the masked token, etc.
  savedConfig: SmartsheetConfigResponse | null;
  // Editable form fields:
  enabled: boolean;
  sheetIdInput: string;
  tokenInput: string; // empty string = keep existing
  showToken: boolean;
  frequency: SmartsheetFrequency;
  mapping: SmartsheetColumnMapping;
  // Available sheet columns (loaded via Test Connection)
  availableColumns: ColumnOption[];
  // Test Connection state
  test: TestState;
  // Recent activity
  recentLog: SmartsheetSyncLogEntry[];
  loadingLog: boolean;
};

type Action =
  | { type: "LOAD_START" }
  | { type: "LOAD_DONE"; config: SmartsheetConfigResponse; log: SmartsheetSyncLogEntry[] }
  | { type: "SAVE_START" }
  | { type: "SAVE_OK"; config: SmartsheetConfigResponse }
  | { type: "SAVE_FAIL"; message: string }
  | { type: "SAVE_DONE" }
  | { type: "SET_ENABLED"; value: boolean }
  | { type: "SET_SHEET_ID"; value: string }
  | { type: "SET_TOKEN"; value: string }
  | { type: "TOGGLE_SHOW_TOKEN" }
  | { type: "SET_FREQUENCY"; value: SmartsheetFrequency }
  | { type: "SET_MAPPING_KEY"; key: keyof SmartsheetColumnMapping; value: string }
  | { type: "TEST_START" }
  | { type: "TEST_OK"; sheetName: string; columns: ColumnOption[] }
  | { type: "TEST_FAIL"; message: string }
  | { type: "CLEAR_MESSAGE" }
  | { type: "REFRESH_LOG"; log: SmartsheetSyncLogEntry[] };

const EMPTY_MAPPING: SmartsheetColumnMapping = {
  entry_id: "",
  logged_at: "",
  headgate: "",
  measurement: "",
  unit: "",
  irrigator: "",
  notes: null,
};

const initialState: State = {
  loading: true,
  saving: false,
  message: null,
  savedConfig: null,
  enabled: false,
  sheetIdInput: "",
  tokenInput: "",
  showToken: false,
  frequency: "hourly",
  mapping: { ...EMPTY_MAPPING },
  availableColumns: [],
  test: { state: "idle" },
  recentLog: [],
  loadingLog: false,
};

function reducer(state: State, action: Action): State {
  switch (action.type) {
    case "LOAD_START":
      return { ...state, loading: true };
    case "LOAD_DONE": {
      const c = action.config;
      return {
        ...state,
        loading: false,
        savedConfig: c,
        enabled: c.syncEnabled,
        sheetIdInput: c.sheetId ?? "",
        // tokenInput stays empty — we don't preload from saved.
        frequency: c.syncFrequency,
        mapping: c.columnMapping ?? { ...EMPTY_MAPPING },
        recentLog: action.log,
      };
    }
    case "SAVE_START":
      return { ...state, saving: true, message: null };
    case "SAVE_OK":
      return {
        ...state,
        saving: false,
        message: { type: "success", text: "Smartsheet settings saved" },
        savedConfig: action.config,
        // Clear token input on save (token is now stored server-side).
        tokenInput: "",
        showToken: false,
      };
    case "SAVE_FAIL":
      return {
        ...state,
        saving: false,
        message: { type: "error", text: action.message },
      };
    case "SAVE_DONE":
      return { ...state, saving: false };
    case "SET_ENABLED":
      return { ...state, enabled: action.value };
    case "SET_SHEET_ID":
      return { ...state, sheetIdInput: action.value };
    case "SET_TOKEN":
      return { ...state, tokenInput: action.value };
    case "TOGGLE_SHOW_TOKEN":
      return { ...state, showToken: !state.showToken };
    case "SET_FREQUENCY":
      return { ...state, frequency: action.value };
    case "SET_MAPPING_KEY":
      return {
        ...state,
        mapping: {
          ...state.mapping,
          [action.key]: action.value === "" ? null : action.value,
        } as SmartsheetColumnMapping,
      };
    case "TEST_START":
      return { ...state, test: { state: "loading" } };
    case "TEST_OK":
      return {
        ...state,
        test: {
          state: "ok",
          sheetName: action.sheetName,
          columnCount: action.columns.length,
          columns: action.columns,
        },
        availableColumns: action.columns,
      };
    case "TEST_FAIL":
      return { ...state, test: { state: "error", message: action.message } };
    case "CLEAR_MESSAGE":
      return { ...state, message: null };
    case "REFRESH_LOG":
      return { ...state, recentLog: action.log };
    default:
      return state;
  }
}

export default function SmartsheetIntegrationCard({
  brandId,
}: {
  brandId: string;
}) {
  const [state, dispatch] = useReducer(reducer, initialState);

  const loadAll = useCallback(async () => {
    dispatch({ type: "LOAD_START" });
    const [config, log] = await Promise.all([
      getSmartsheetConfig(brandId),
      listSmartsheetSyncLog(brandId, 10),
    ]);
    dispatch({ type: "LOAD_DONE", config, log });
  }, [brandId]);

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

  async function handleSave(e: React.FormEvent) {
    e.preventDefault();
    dispatch({ type: "SAVE_START" });
    const result = await saveSmartsheetConfig(brandId, {
      sheetId: state.sheetIdInput,
      token: state.tokenInput,
      syncEnabled: state.enabled,
      syncFrequency: state.frequency,
      columnMapping: state.mapping,
    });
    if (result.success && result.config) {
      dispatch({ type: "SAVE_OK", config: result.config });
      // Refresh log so any pending activity from this turn is visible.
      const log = await listSmartsheetSyncLog(brandId, 10);
      dispatch({ type: "REFRESH_LOG", log });
    } else {
      dispatch({ type: "SAVE_FAIL", message: result.error ?? "Save failed" });
    }
  }

  async function handleTest() {
    if (!state.sheetIdInput) {
      dispatch({ type: "TEST_FAIL", message: "Enter a Sheet URL or ID first" });
      return;
    }
    if (!state.tokenInput && !state.savedConfig?.hasToken) {
      dispatch({
        type: "TEST_FAIL",
        message: "Paste your API token to test, or save the config first",
      });
      return;
    }
    dispatch({ type: "TEST_START" });
    const result = await testSmartsheetConnection(
      brandId,
      state.sheetIdInput,
      state.tokenInput,
    );
    if (result.success) {
      dispatch({
        type: "TEST_OK",
        sheetName: result.sheetName,
        columns: result.columns,
      });
    } else {
      dispatch({ type: "TEST_FAIL", message: result.error });
    }
  }

  if (state.loading) {
    return (
      <Card title="Smartsheet Integration" subtitle="Loading…">
        <p className="text-sm text-[#5a5d5a]">Reading saved configuration.</p>
      </Card>
    );
  }

  const noTokenYet = !state.savedConfig?.hasToken && state.tokenInput.length === 0;

  return (
    <form onSubmit={handleSave} className="space-y-6">
      {state.message && (
        <div
          className={`rounded-lg border px-4 py-3 text-sm font-medium ${
            state.message.type === "success"
              ? "border-[#1a4d2e] bg-[#1a4d2e]/5 text-[#1a4d2e]"
              : "border-[#a4452b] bg-[#a4452b]/5 text-[#a4452b]"
          }`}
        >
          {state.message.text}
        </div>
      )}

      <Card
        title="Smartsheet Integration"
        subtitle="Push every new water log entry to a Smartsheet sheet automatically."
      >
        <ToggleRow
          label="Enable"
          description="When disabled, no new rows are pushed. Existing rows in Smartsheet are untouched."
          value={state.enabled}
          onChange={(v) => dispatch({ type: "SET_ENABLED", value: v })}
        />
      </Card>

      <Card
        title="Connection"
        subtitle="Smartsheet API token + target sheet."
      >
        {/* Sheet */}
        <div className="space-y-1">
          <label
            htmlFor="smartsheet-sheet"
            className="block text-xs font-medium text-[#5a5d5a]"
          >
            Sheet URL or sheet ID
          </label>
          <input
            id="smartsheet-sheet"
            type="text"
            value={state.sheetIdInput}
            onChange={(e) =>
              dispatch({ type: "SET_SHEET_ID", value: e.target.value })
            }
            placeholder="https://app.smartsheet.com/sheets/AbCdEfGhIjKlMn  or  123456789012345"
            className="w-full rounded-lg border border-[#d4d9d3] bg-white px-4 py-2.5 font-mono text-sm outline-none focus:border-[#1a4d2e] focus:ring-1 focus:ring-[#1a4d2e]"
            autoComplete="off"
          />
          <p className="text-xs text-[#8a8b88]">
            Paste the share URL from your browser address bar, or the
            numeric sheet ID. If a share URL doesn&apos;t work, use the
            numeric ID from <em>File → Properties</em> in Smartsheet.
          </p>
        </div>

        {/* Token */}
        <div className="mt-4 space-y-1">
          <label
            htmlFor="smartsheet-token"
            className="block text-xs font-medium text-[#5a5d5a]"
          >
            API access token
          </label>
          <div className="flex gap-2">
            <input
              id="smartsheet-token"
              type={state.showToken ? "text" : "password"}
              value={state.tokenInput}
              onChange={(e) =>
                dispatch({ type: "SET_TOKEN", value: e.target.value })
              }
              placeholder={
                state.savedConfig?.hasToken
                  ? `Leave blank to keep the saved token (${state.savedConfig.maskedToken ?? "••••"})`
                  : "Paste your Smartsheet API token"
              }
              className="flex-1 rounded-lg border border-[#d4d9d3] bg-white px-4 py-2.5 font-mono text-sm outline-none focus:border-[#1a4d2e] focus:ring-1 focus:ring-[#1a4d2e]"
              autoComplete="off"
            />
            <button
              type="button"
              onClick={() => dispatch({ type: "TOGGLE_SHOW_TOKEN" })}
              className="rounded-lg border border-[#d4d9d3] bg-white px-3 text-xs font-medium text-[#5a5d5a] hover:bg-[#f4f1e8]"
              aria-label={state.showToken ? "Hide token" : "Show token"}
            >
              {state.showToken ? "Hide" : "Show"}
            </button>
          </div>
          <p className="text-xs text-[#8a8b88]">
            Generate a token at{" "}
            <a
              href="https://app.smartsheet.com/b/home"
              target="_blank"
              rel="noopener noreferrer"
              className="text-[#1a4d2e] underline underline-offset-2"
            >
              app.smartsheet.com
            </a>{" "}
            → <span className="font-mono">Account</span> →{" "}
            <span className="font-mono">Personal Settings</span> →{" "}
            <span className="font-mono">API Access</span>. The token is
            encrypted with AES-256-GCM at rest.
          </p>
        </div>

        {/* Test Connection */}
        <div className="mt-4 flex items-center gap-3">
          <button
            type="button"
            onClick={handleTest}
            disabled={state.test.state === "loading"}
            className="rounded-lg border border-[#1a4d2e] bg-white px-4 py-2 text-sm font-semibold text-[#1a4d2e] transition hover:bg-[#1a4d2e] hover:text-white disabled:opacity-50"
          >
            {state.test.state === "loading" ? "Testing…" : "Test Connection"}
          </button>
          <TestResultPanel test={state.test} />
        </div>
      </Card>

      <Card
        title="Sync frequency"
        subtitle="How often new water log entries are pushed to Smartsheet."
      >
        <div className="space-y-2">
          {(Object.keys(FREQUENCY_LABELS) as SmartsheetFrequency[]).map((f) => (
            <label
              key={f}
              className={`flex cursor-pointer items-start gap-3 rounded-lg border px-4 py-3 transition ${
                state.frequency === f
                  ? "border-[#1a4d2e] bg-[#1a4d2e]/5"
                  : "border-[#d4d9d3] bg-white hover:border-[#1a4d2e]"
              }`}
            >
              <input
                type="radio"
                name="smartsheet-frequency"
                value={f}
                checked={state.frequency === f}
                onChange={() =>
                  dispatch({ type: "SET_FREQUENCY", value: f })
                }
                className="mt-0.5 accent-[#1a4d2e]"
              />
              <span className="flex-1 text-sm font-medium text-[#1d1d1f]">
                {FREQUENCY_LABELS[f]}
              </span>
            </label>
          ))}
        </div>
      </Card>

      <Card
        title="Column mapping"
        subtitle="Map our water log fields to columns in your Smartsheet. entry_id and logged_at are required."
      >
        {state.availableColumns.length === 0 ? (
          <p className="text-xs text-[#8a8b88]">
            Run <strong>Test Connection</strong> above to load the sheet&apos;s
            columns. You can also paste column IDs manually below.
          </p>
        ) : (
          <p className="text-xs text-[#8a8b88]">
            Loaded {state.availableColumns.length} columns from sheet{" "}
            <span className="font-mono">
              {state.test.state === "ok" ? state.test.sheetName : "—"}
            </span>
            . Pick from the dropdowns below.
          </p>
        )}

        <div className="mt-4 space-y-3">
          {(Object.keys(COLUMN_LABELS) as Array<keyof SmartsheetColumnMapping>).map(
            (key) => {
              const required = REQUIRED_COLUMNS.includes(key);
              const value = state.mapping[key];
              const valueAsString = value ?? "";
              return (
                <div key={key} className="flex items-center gap-3">
                  <label
                    htmlFor={`map-${key}`}
                    className="w-1/3 text-sm font-medium text-[#1d1d1f]"
                  >
                    {COLUMN_LABELS[key]}
                    {required && (
                      <span className="ml-1 text-xs text-[#a4452b]">
                        required
                      </span>
                    )}
                  </label>
                  {state.availableColumns.length > 0 ? (
                    <select
                      id={`map-${key}`}
                      value={valueAsString}
                      onChange={(e) =>
                        dispatch({
                          type: "SET_MAPPING_KEY",
                          key,
                          value: e.target.value,
                        })
                      }
                      className="flex-1 rounded-lg border border-[#d4d9d3] bg-white px-3 py-2 text-sm outline-none focus:border-[#1a4d2e] focus:ring-1 focus:ring-[#1a4d2e]"
                    >
                      <option value="">
                        — {required ? "Select a column" : "Not mapped"} —
                      </option>
                      {state.availableColumns.map((c) => (
                        <option key={c.id} value={c.id}>
                          {c.title}
                          {c.type !== "TEXT_NUMBER"
                            ? ` (${c.type.toLowerCase()})`
                            : ""}
                        </option>
                      ))}
                    </select>
                  ) : (
                    <input
                      id={`map-${key}`}
                      type="text"
                      value={valueAsString}
                      onChange={(e) =>
                        dispatch({
                          type: "SET_MAPPING_KEY",
                          key,
                          value: e.target.value,
                        })
                      }
                      placeholder="Column ID (numeric)"
                      className="flex-1 rounded-lg border border-[#d4d9d3] bg-white px-3 py-2 font-mono text-sm outline-none focus:border-[#1a4d2e] focus:ring-1 focus:ring-[#1a4d2e]"
                    />
                  )}
                </div>
              );
            },
          )}
        </div>
      </Card>

      <Card
        title="Recent activity"
        subtitle="Last 10 sync attempts. Use this to spot token / sheet issues quickly."
      >
        {state.loadingLog ? (
          <p className="text-sm text-[#5a5d5a]">Loading…</p>
        ) : state.recentLog.length === 0 ? (
          <p className="text-sm text-[#5a5d5a]">
            No sync attempts yet. Save the config and submit a water log
            entry from <code className="rounded bg-[#f4f1e8] px-1 py-0.5 font-mono text-xs">/water</code>.
          </p>
        ) : (
          <ul className="divide-y divide-[#d4d9d3]">
            {state.recentLog.map((log) => (
              <li
                key={log.id}
                className="flex items-start gap-3 py-3 first:pt-0 last:pb-0"
              >
                <span
                  className={`mt-0.5 inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-full text-xs font-bold text-white ${
                    log.success ? "bg-[#1a4d2e]" : "bg-[#a4452b]"
                  }`}
                  aria-label={log.success ? "success" : "failure"}
                >
                  {log.success ? "✓" : "✗"}
                </span>
                <div className="min-w-0 flex-1">
                  <div className="flex flex-wrap items-baseline gap-x-3 gap-y-1 text-xs">
                    <span className="font-mono font-semibold text-[#1d1d1f]">
                      {log.action}
                    </span>
                    <span className="text-[#5a5d5a]">
                      {formatDateTime(log.createdAt)}
                    </span>
                    {log.durationMs != null && (
                      <span className="text-[#8a8b88]">
                        {log.durationMs}ms
                      </span>
                    )}
                  </div>
                  {log.error && (
                    <p className="mt-0.5 text-xs text-[#a4452b]">{log.error}</p>
                  )}
                </div>
              </li>
            ))}
          </ul>
        )}
      </Card>

      <button
        type="submit"
        disabled={state.saving || noTokenYet}
        className="w-full rounded-lg bg-[#1a4d2e] px-6 py-3.5 text-sm font-semibold uppercase tracking-wider text-white transition hover:bg-[#143d24] disabled:opacity-50"
      >
        {state.saving ? "Saving…" : "Save Settings"}
      </button>

      {noTokenYet && (
        <p className="text-center text-xs text-[#8a8b88]">
          Paste an API token above to enable Save.
        </p>
      )}
    </form>
  );
}

// ── Subcomponents (mirror the parent settings page style) ──────────────────

function Card({
  title,
  subtitle,
  children,
}: {
  title: string;
  subtitle?: string;
  children: React.ReactNode;
}) {
  return (
    <section className="rounded-xl border border-[#d4d9d3] bg-white p-5 shadow-sm">
      <header className="mb-4">
        <h2 className="text-base font-semibold text-[#1d1d1f]">{title}</h2>
        {subtitle && <p className="mt-0.5 text-xs text-[#5a5d5a]">{subtitle}</p>}
      </header>
      {children}
    </section>
  );
}

function ToggleRow({
  label,
  description,
  value,
  onChange,
}: {
  label: string;
  description?: string;
  value: boolean;
  onChange: (v: boolean) => void;
}) {
  return (
    <div className="flex items-center justify-between gap-3">
      <div className="min-w-0 flex-1">
        <p className="text-sm font-medium text-[#1d1d1f]">{label}</p>
        {description && (
          <p className="mt-0.5 text-xs text-[#5a5d5a]">{description}</p>
        )}
      </div>
      <button
        type="button"
        role="switch"
        aria-checked={value}
        aria-label={label}
        onClick={() => onChange(!value)}
        className={`relative inline-flex h-6 w-11 shrink-0 items-center rounded-full transition-colors ${
          value ? "bg-[#1a4d2e]" : "bg-[#d4d9d3]"
        }`}
      >
        <span
          className={`inline-block h-4 w-4 transform rounded-full bg-white shadow transition-transform ${
            value ? "translate-x-6" : "translate-x-1"
          }`}
        />
      </button>
    </div>
  );
}

function TestResultPanel({ test }: { test: TestState }) {
  if (test.state === "idle") return null;
  if (test.state === "loading") {
    return <span className="text-sm text-[#5a5d5a]">Testing…</span>;
  }
  if (test.state === "ok") {
    return (
      <div className="flex-1 rounded-lg border border-[#1a4d2e] bg-[#1a4d2e]/5 px-3 py-2 text-xs">
        <p className="font-semibold text-[#1a4d2e]">
          ✓ Connected to &ldquo;{test.sheetName}&rdquo; ({test.columnCount} columns)
        </p>
      </div>
    );
  }
  return (
    <div className="flex-1 rounded-lg border border-[#a4452b] bg-[#a4452b]/5 px-3 py-2 text-xs">
      <p className="font-semibold text-[#a4452b]">✗ {test.message}</p>
    </div>
  );
}