import {Plus, Send, Trash2} from 'lucide-react';
import {FormEvent, useMemo, useState} from 'react';

import {debugAdminHttp} from '../api/adminApiClient';
import type {
  AdminDebugHeaderInput,
  AdminDebugHttpMethod,
  AdminDebugHttpResponse,
} from '../api/adminApiTypes';
import {useAdminWriteConfirm} from '../components/useAdminWriteConfirm';
import {formatUnknownJson, handlePageError} from './pageUtils';

interface AdminDebugHttpPageProps {
  token: string;
  onUnauthorized: (message?: string) => void;
}

const httpMethods: AdminDebugHttpMethod[] = [
  'GET',
  'POST',
  'PUT',
  'PATCH',
  'DELETE',
];

export function AdminDebugHttpPage({
  token,
  onUnauthorized,
}: AdminDebugHttpPageProps) {
  const [method, setMethod] = useState<AdminDebugHttpMethod>('GET');
  const [path, setPath] = useState('/healthz');
  const [body, setBody] = useState('');
  const [headers, setHeaders] = useState<AdminDebugHeaderInput[]>([]);
  const [result, setResult] = useState<AdminDebugHttpResponse | null>(null);
  const [errorMessage, setErrorMessage] = useState('');
  const [isSubmitting, setIsSubmitting] = useState(false);
  const {confirmWrite, confirmDialog} = useAdminWriteConfirm();

  const jsonPreview = useMemo(
    () => formatUnknownJson(result?.bodyJson),
    [result?.bodyJson],
  );

  async function handleSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (isSubmitting) {
      return;
    }

    setErrorMessage('');
    if (method !== 'GET') {
      const confirmed = await confirmWrite({
        action: `${method} 调试请求`,
        target: path.trim(),
      });
      if (!confirmed) {
        return;
      }
    }

    setIsSubmitting(true);
    try {
      const response = await debugAdminHttp(token, {
        method,
        path: path.trim(),
        headers: headers.filter((header) => header.name.trim()),
        body,
      });
      setResult(response);
    } catch (error: unknown) {
      handlePageError(error, onUnauthorized, setErrorMessage);
    } finally {
      setIsSubmitting(false);
    }
  }

  return (
    <section className="admin-page">
      <div className="admin-page-heading">
        <div>
          <h2>API 调试</h2>
          <p>受控同源请求</p>
        </div>
      </div>

      <div className="admin-two-column">
        <form className="admin-panel admin-form" onSubmit={handleSubmit}>
          <div className="admin-form-row">
            <label className="admin-field admin-field-compact">
              <span>Method</span>
              <select
                value={method}
                onChange={(event) =>
                  setMethod(event.target.value as AdminDebugHttpMethod)
                }
              >
                {httpMethods.map((item) => (
                  <option key={item} value={item}>
                    {item}
                  </option>
                ))}
              </select>
            </label>
            <label className="admin-field admin-field-fill">
              <span>Path</span>
              <input
                value={path}
                onChange={(event) => setPath(event.target.value)}
              />
            </label>
          </div>

          <section className="admin-subsection">
            <div className="admin-subsection-heading">
              <span>Headers</span>
              <button
                className="admin-ghost-button"
                type="button"
                onClick={() =>
                  setHeaders((current) => [
                    ...current,
                    {name: '', value: ''},
                  ])
                }
              >
                <Plus size={16} aria-hidden="true" />
              </button>
            </div>
            <div className="admin-header-editor">
              {headers.map((header, index) => (
                <div className="admin-header-row" key={index}>
                  <input
                    value={header.name}
                    onChange={(event) =>
                      setHeaders((current) =>
                        current.map((item, itemIndex) =>
                          itemIndex === index
                            ? {...item, name: event.target.value}
                            : item,
                        ),
                      )
                    }
                  />
                  <input
                    value={header.value}
                    onChange={(event) =>
                      setHeaders((current) =>
                        current.map((item, itemIndex) =>
                          itemIndex === index
                            ? {...item, value: event.target.value}
                            : item,
                        ),
                      )
                    }
                  />
                  <button
                    className="admin-ghost-button"
                    title="移除"
                    type="button"
                    onClick={() =>
                      setHeaders((current) =>
                        current.filter((_, itemIndex) => itemIndex !== index),
                      )
                    }
                  >
                    <Trash2 size={16} aria-hidden="true" />
                  </button>
                </div>
              ))}
            </div>
          </section>

          <label className="admin-field">
            <span>Body</span>
            <textarea
              rows={9}
              value={body}
              onChange={(event) => setBody(event.target.value)}
            />
          </label>

          {errorMessage ? (
            <div className="admin-alert" role="status">
              {errorMessage}
            </div>
          ) : null}

          <button
            className="admin-primary-button"
            disabled={isSubmitting || !path.trim().startsWith('/')}
            type="submit"
          >
            <Send size={17} aria-hidden="true" />
            <span>{isSubmitting ? '发送中' : '发送'}</span>
          </button>
        </form>

        <section className="admin-panel admin-result-panel">
          <div className="admin-panel-heading">
            <h3>结果</h3>
            <span>{result ? `${result.status} ${result.statusText}` : '-'}</span>
          </div>
          {result ? (
            <>
              <dl className="admin-info-list">
                <div>
                  <dt>Status</dt>
                  <dd>{result.status}</dd>
                </div>
                <div>
                  <dt>Headers</dt>
                  <dd>{result.headers.length}</dd>
                </div>
              </dl>
              <pre className="admin-code-block">
                {jsonPreview || result.bodyText || '(empty)'}
              </pre>
            </>
          ) : (
            <div className="admin-empty-state">暂无结果</div>
          )}
        </section>
      </div>
      {confirmDialog}
    </section>
  );
}
