import React, { useEffect, useState } from 'react';
import { agentSettingsBridge } from '../../lib/agentSettingsBridge';
import {
  AgentConfigStatus,
  AgentTaskRoute,
  ProviderMode,
  TASK_LABELS,
  TASK_PROFILES,
  TaskProfile,
} from '../../types/agentSettings';

interface AgentSettingsModalProps {
  isOpen: boolean;
  status: AgentConfigStatus | null;
  onClose: () => void;
  onStatusChange: (status: AgentConfigStatus) => void;
}

const inputClassName =
  'w-full rounded border border-[#2a2a2a] bg-[#111111] px-3 py-2 text-sm font-mono text-[#e0e0e0] outline-none transition-colors focus:border-[#58a6ff]';

const textareaClassName = `${inputClassName} min-h-28 resize-y`;

const buttonClassName =
  'rounded border border-[#2a2a2a] bg-[#151515] px-3 py-2 text-xs font-mono text-[#e0e0e0] transition-colors hover:border-[#58a6ff] hover:text-[#58a6ff] disabled:cursor-not-allowed disabled:opacity-50';

const normalizeModelList = (value: string): string[] => {
  const items = value
    .split(/[\n,]/)
    .map((item) => item.trim())
    .filter(Boolean);

  return Array.from(new Set(items));
};

const mergeTaskDefaults = (
  taskDefaults: Partial<Record<TaskProfile, AgentTaskRoute>>,
  defaultRemoteModel: string,
  localModels: string[],
): Record<TaskProfile, AgentTaskRoute> => {
  const fallbackLocalModel = localModels[0] ?? '';

  return TASK_PROFILES.reduce((acc, profile) => {
    const existing = taskDefaults[profile];
    acc[profile] = existing ?? {
      providerMode: 'remote',
      model: defaultRemoteModel || fallbackLocalModel,
    };
    return acc;
  }, {} as Record<TaskProfile, AgentTaskRoute>);
};

export const AgentSettingsModal: React.FC<AgentSettingsModalProps> = ({
  isOpen,
  status,
  onClose,
  onStatusChange,
}) => {
  const [remoteEnabled, setRemoteEnabled] = useState(true);
  const [remoteBaseUrl, setRemoteBaseUrl] = useState('');
  const [defaultRemoteModel, setDefaultRemoteModel] = useState('');
  const [localEnabled, setLocalEnabled] = useState(false);
  const [localBaseUrl, setLocalBaseUrl] = useState('');
  const [localAvailableModelsText, setLocalAvailableModelsText] = useState('');
  const [taskDefaults, setTaskDefaults] = useState<Record<TaskProfile, AgentTaskRoute>>(
    mergeTaskDefaults({}, '', []),
  );
  const [remoteApiKey, setRemoteApiKey] = useState('');
  const [error, setError] = useState<string | null>(null);
  const [success, setSuccess] = useState<string | null>(null);
  const [localStatusMessage, setLocalStatusMessage] = useState<string | null>(null);
  const [isBusy, setIsBusy] = useState(false);

  useEffect(() => {
    if (!status || !isOpen) {
      return;
    }

    setRemoteEnabled(status.remoteEnabled);
    setRemoteBaseUrl(status.remoteBaseUrl);
    setDefaultRemoteModel(status.defaultRemoteModel);
    setLocalEnabled(status.localEnabled);
    setLocalBaseUrl(status.localBaseUrl);
    setLocalAvailableModelsText(status.localAvailableModels.join('\n'));
    setTaskDefaults(
      mergeTaskDefaults(
        status.taskDefaults,
        status.defaultRemoteModel,
        status.localAvailableModels,
      ),
    );
    setRemoteApiKey('');
    setError(null);
    setSuccess(null);
    setLocalStatusMessage(null);
  }, [isOpen, status]);

  if (!isOpen || !status) {
    return null;
  }

  const localAvailableModels = normalizeModelList(localAvailableModelsText);

  const runtimeRequest = {
    remoteEnabled,
    remoteBaseUrl,
    defaultRemoteModel,
    localEnabled,
    localBaseUrl,
    localAvailableModels,
    taskDefaults,
  };

  const setTaskRoute = (
    task: TaskProfile,
    updater: (route: AgentTaskRoute) => AgentTaskRoute,
  ) => {
    setTaskDefaults((current) => ({
      ...current,
      [task]: updater(current[task]),
    }));
  };

  const saveRuntimeConfig = async () => {
    const nextStatus = await agentSettingsBridge.saveRuntimeConfig(runtimeRequest);
    onStatusChange(nextStatus);
    return nextStatus;
  };

  const handleSaveRuntime = async () => {
    setIsBusy(true);
    setError(null);
    setSuccess(null);
    try {
      await saveRuntimeConfig();
      setSuccess('Provider routing saved.');
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to save runtime settings.');
    } finally {
      setIsBusy(false);
    }
  };

  const handleSaveRemoteApiKey = async () => {
    setIsBusy(true);
    setError(null);
    setSuccess(null);
    try {
      const savedStatus = await saveRuntimeConfig();
      const nextStatus = await agentSettingsBridge.updateRemoteApiKey({ apiKey: remoteApiKey });
      onStatusChange({ ...savedStatus, ...nextStatus });
      setRemoteApiKey('');
      setSuccess(
        status.hasRemoteApiKey
          ? 'Remote API key updated.'
          : 'Remote API key saved.',
      );
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to save remote API key.');
    } finally {
      setIsBusy(false);
    }
  };

  const handleClearRemoteApiKey = async () => {
    setIsBusy(true);
    setError(null);
    setSuccess(null);
    try {
      const savedStatus = await saveRuntimeConfig();
      const nextStatus = await agentSettingsBridge.clearRemoteApiKey();
      onStatusChange({ ...savedStatus, ...nextStatus });
      setRemoteApiKey('');
      setSuccess('Remote API key cleared.');
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to clear remote API key.');
    } finally {
      setIsBusy(false);
    }
  };

  const handleDiscoverLocalModels = async () => {
    setIsBusy(true);
    setError(null);
    setSuccess(null);
    setLocalStatusMessage(null);
    try {
      const result = await agentSettingsBridge.listLocalModels();
      setLocalAvailableModelsText(result.models.join('\n'));
      setTaskDefaults((current) => {
        const next = { ...current };
        for (const profile of TASK_PROFILES) {
          if (
            next[profile].providerMode === 'local' &&
            !next[profile].model.trim() &&
            result.models[0]
          ) {
            next[profile] = { ...next[profile], model: result.models[0] };
          }
        }
        return next;
      });
      setLocalStatusMessage(
        result.reachable
          ? `Discovered ${result.models.length} local model(s).`
          : 'Loaded stored local models because the sidecar was unreachable.',
      );
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to list local models.');
    } finally {
      setIsBusy(false);
    }
  };

  const handleCheckLocalHealth = async () => {
    setIsBusy(true);
    setError(null);
    setSuccess(null);
    try {
      const result = await agentSettingsBridge.checkLocalProviderHealth();
      setLocalStatusMessage(result.message);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to reach local provider.');
    } finally {
      setIsBusy(false);
    }
  };

  const handleTaskProviderChange = (task: TaskProfile, providerMode: ProviderMode) => {
    const suggestedLocalModel = localAvailableModels[0] ?? '';
    setTaskRoute(task, (route) => ({
      providerMode,
      model:
        providerMode === 'remote'
          ? route.providerMode === 'remote' && route.model.trim()
            ? route.model
            : defaultRemoteModel
          : route.providerMode === 'local' && route.model.trim()
            ? route.model
            : suggestedLocalModel,
    }));
  };

  const handleDefaultRemoteModelChange = (nextValue: string) => {
    const previousValue = defaultRemoteModel;
    setDefaultRemoteModel(nextValue);
    setTaskDefaults((current) => {
      const next = { ...current };
      for (const profile of TASK_PROFILES) {
        if (
          next[profile].providerMode === 'remote' &&
          next[profile].model.trim() === previousValue.trim()
        ) {
          next[profile] = { ...next[profile], model: nextValue };
        }
      }
      return next;
    });
  };

  return (
    <div className="fixed inset-0 z-40 flex items-center justify-center bg-black/70 px-4">
      <div className="max-h-[90vh] w-full max-w-4xl overflow-y-auto rounded-xl border border-[#2a2a2a] bg-[#0a0a0a] shadow-2xl">
        <div className="flex items-center justify-between border-b border-[#2a2a2a] px-5 py-4">
          <div>
            <h2 className="text-sm font-mono font-semibold text-[#e0e0e0]">AI Settings</h2>
            <p className="mt-1 text-xs font-mono text-[#888888]">
              Configure remote and local providers, then assign a default provider/model per task.
            </p>
          </div>
          <button
            type="button"
            onClick={onClose}
            className="rounded px-2 py-1 text-xs font-mono text-[#888888] transition-colors hover:bg-[#1a1a1a] hover:text-[#e0e0e0]"
          >
            Close
          </button>
        </div>

        <div className="space-y-5 px-5 py-5">
          <section className="rounded-lg border border-[#2a2a2a] bg-[#111111] p-4">
            <div className="mb-4 flex items-center justify-between">
              <div>
                <h3 className="text-xs font-mono uppercase tracking-wide text-[#888888]">
                  Runtime Status
                </h3>
                <p className="mt-1 text-sm font-mono text-[#e0e0e0]">
                  {status.configured ? 'Configured' : 'Routing incomplete'}
                </p>
              </div>
              <div className="text-right text-xs font-mono text-[#888888]">
                <div>Remote ready: {status.remoteConfigured ? 'yes' : 'no'}</div>
                <div>Local ready: {status.localConfigured ? 'yes' : 'no'}</div>
              </div>
            </div>
          </section>

          <section className="rounded-lg border border-[#2a2a2a] bg-[#111111] p-4">
            <div className="mb-4 flex items-center justify-between">
              <div>
                <h3 className="text-xs font-mono uppercase tracking-wide text-[#888888]">
                  Remote Provider
                </h3>
                <p className="mt-1 text-xs font-mono text-[#888888]">
                  OpenAI-compatible HTTP endpoint.
                </p>
              </div>
              <label className="flex items-center gap-2 text-xs font-mono text-[#e0e0e0]">
                <input
                  type="checkbox"
                  checked={remoteEnabled}
                  onChange={(event) => setRemoteEnabled(event.target.checked)}
                />
                Enabled
              </label>
            </div>

            <div className="grid gap-4 md:grid-cols-2">
              <label className="block">
                <span className="mb-2 block text-xs font-mono text-[#888888]">
                  Remote Base URL
                </span>
                <input
                  className={inputClassName}
                  value={remoteBaseUrl}
                  onChange={(event) => setRemoteBaseUrl(event.target.value)}
                  placeholder="https://api.z.ai/api/coding/paas/v4"
                />
              </label>

              <label className="block">
                <span className="mb-2 block text-xs font-mono text-[#888888]">
                  Default Remote Model
                </span>
                <input
                  className={inputClassName}
                  value={defaultRemoteModel}
                  onChange={(event) => handleDefaultRemoteModelChange(event.target.value)}
                  placeholder="glm-5.1"
                />
              </label>
            </div>
          </section>

          <section className="rounded-lg border border-[#2a2a2a] bg-[#111111] p-4">
            <div className="mb-4 flex items-center justify-between">
              <div>
                <h3 className="text-xs font-mono uppercase tracking-wide text-[#888888]">
                  Local Provider
                </h3>
                <p className="mt-1 text-xs font-mono text-[#888888]">
                  Running Mistral HTTP sidecar on localhost.
                </p>
              </div>
              <label className="flex items-center gap-2 text-xs font-mono text-[#e0e0e0]">
                <input
                  type="checkbox"
                  checked={localEnabled}
                  onChange={(event) => setLocalEnabled(event.target.checked)}
                />
                Enabled
              </label>
            </div>

            <div className="grid gap-4 md:grid-cols-[minmax(0,1fr)_auto]">
              <label className="block">
                <span className="mb-2 block text-xs font-mono text-[#888888]">
                  Local Base URL
                </span>
                <input
                  className={inputClassName}
                  value={localBaseUrl}
                  onChange={(event) => setLocalBaseUrl(event.target.value)}
                  placeholder="http://127.0.0.1:1234"
                />
              </label>
              <div className="flex items-end gap-2">
                <button
                  type="button"
                  onClick={handleCheckLocalHealth}
                  disabled={isBusy}
                  className={buttonClassName}
                >
                  Check Local
                </button>
                <button
                  type="button"
                  onClick={handleDiscoverLocalModels}
                  disabled={isBusy}
                  className={buttonClassName}
                >
                  Discover Models
                </button>
              </div>
            </div>

            <label className="mt-4 block">
              <span className="mb-2 block text-xs font-mono text-[#888888]">
                Available Local Models
              </span>
              <textarea
                className={textareaClassName}
                value={localAvailableModelsText}
                onChange={(event) => setLocalAvailableModelsText(event.target.value)}
                placeholder={'qwen2.5:3b-instruct\nmistral-small'}
              />
            </label>

            {localStatusMessage ? (
              <div className="mt-4 rounded border border-[#2a2a2a] bg-[#0d0d0d] px-3 py-2 text-xs font-mono text-[#9fb3c8]">
                {localStatusMessage}
              </div>
            ) : null}
          </section>

          <section className="rounded-lg border border-[#2a2a2a] bg-[#111111] p-4">
            <div className="mb-4">
              <h3 className="text-xs font-mono uppercase tracking-wide text-[#888888]">
                Task Routing
              </h3>
              <p className="mt-1 text-xs font-mono text-[#888888]">
                Choose the default provider and model for each harness task.
              </p>
            </div>

            <div className="space-y-3">
              {TASK_PROFILES.map((task) => (
                <div
                  key={task}
                  className="grid gap-3 rounded border border-[#1d1d1d] bg-[#0d0d0d] p-3 md:grid-cols-[180px_140px_minmax(0,1fr)]"
                >
                  <div className="text-sm font-mono text-[#e0e0e0]">{TASK_LABELS[task]}</div>
                  <label className="block">
                    <span className="mb-2 block text-xs font-mono text-[#888888]">Provider</span>
                    <select
                      className={inputClassName}
                      value={taskDefaults[task].providerMode}
                      onChange={(event) =>
                        handleTaskProviderChange(task, event.target.value as ProviderMode)
                      }
                    >
                      <option value="remote">remote</option>
                      <option value="local">local</option>
                    </select>
                  </label>
                  <label className="block">
                    <span className="mb-2 block text-xs font-mono text-[#888888]">Model</span>
                    <input
                      list={taskDefaults[task].providerMode === 'local' ? `${task}-local-models` : undefined}
                      className={inputClassName}
                      value={taskDefaults[task].model}
                      onChange={(event) =>
                        setTaskRoute(task, (route) => ({ ...route, model: event.target.value }))
                      }
                      placeholder={
                        taskDefaults[task].providerMode === 'remote'
                          ? defaultRemoteModel || 'Remote model'
                          : 'Local model'
                      }
                    />
                    {taskDefaults[task].providerMode === 'local' ? (
                      <datalist id={`${task}-local-models`}>
                        {localAvailableModels.map((model) => (
                          <option key={`${task}-${model}`} value={model} />
                        ))}
                      </datalist>
                    ) : null}
                  </label>
                </div>
              ))}
            </div>

            <div className="mt-4 flex justify-end">
              <button
                type="button"
                onClick={handleSaveRuntime}
                disabled={isBusy}
                className={buttonClassName}
              >
                Save Routing
              </button>
            </div>
          </section>

          <section className="rounded-lg border border-[#2a2a2a] bg-[#111111] p-4">
            <h3 className="text-xs font-mono uppercase tracking-wide text-[#888888]">
              Remote API Key
            </h3>
            <p className="mt-2 text-xs font-mono text-[#888888]">
              Stored in plain text for the remote OpenAI-compatible provider only.
            </p>
            <label className="mt-4 block">
              <span className="mb-2 block text-xs font-mono text-[#888888]">
                {status.hasRemoteApiKey ? 'Replace Remote API Key' : 'Remote API Key'}
              </span>
              <input
                type="password"
                className={inputClassName}
                value={remoteApiKey}
                onChange={(event) => setRemoteApiKey(event.target.value)}
                placeholder="Enter remote API key"
              />
            </label>

            <div className="mt-4 flex justify-between">
              <div>
                {status.hasRemoteApiKey ? (
                  <button
                    type="button"
                    onClick={handleClearRemoteApiKey}
                    disabled={isBusy}
                    className="rounded border border-[#2a2a2a] bg-[#151515] px-3 py-2 text-xs font-mono text-[#ff7b72] transition-colors hover:border-[#ff7b72] disabled:cursor-not-allowed disabled:opacity-50"
                  >
                    Clear Key
                  </button>
                ) : null}
              </div>
              <button
                type="button"
                onClick={handleSaveRemoteApiKey}
                disabled={isBusy}
                className={buttonClassName}
              >
                {status.hasRemoteApiKey ? 'Save Routing & Update Key' : 'Save Routing & Save Key'}
              </button>
            </div>
          </section>

          {success ? (
            <div className="rounded border border-[#214f31] bg-[#102417] px-3 py-2 text-xs font-mono text-[#9ee6b3]">
              {success}
            </div>
          ) : null}

          {error ? (
            <div className="rounded border border-[#5c2b2b] bg-[#211313] px-3 py-2 text-xs font-mono text-[#ffb4b4]">
              {error}
            </div>
          ) : null}
        </div>
      </div>
    </div>
  );
};
