/**
 * Structured renderers for OpenAPI parameters, request bodies, and responses.
 * Replaces raw JSON.stringify output with readable tables and schema trees.
 */

import { useI18n } from '../lib/i18n';

/* ===== Helpers ===== */

type SchemaObj = {
  type?: string;
  format?: string;
  description?: string;
  enum?: unknown[];
  items?: SchemaObj;
  properties?: Record<string, SchemaObj>;
  required?: string[];
  additionalProperties?: boolean | SchemaObj;
  oneOf?: SchemaObj[];
  anyOf?: SchemaObj[];
  allOf?: SchemaObj[];
  default?: unknown;
  example?: unknown;
  nullable?: boolean;
  minimum?: number;
  maximum?: number;
  minLength?: number;
  maxLength?: number;
  pattern?: string;
  [key: string]: unknown;
};

type Parameter = {
  name: string;
  in: string;
  required?: boolean;
  description?: string;
  schema?: SchemaObj;
  type?: string;
  format?: string;
  enum?: unknown[];
  [key: string]: unknown;
};

function resolveType(schema?: SchemaObj): string {
  if (!schema) return '—';
  if (schema.type === 'array' && schema.items) {
    return `${resolveType(schema.items)}[]`;
  }
  if (schema.oneOf) return schema.oneOf.map(resolveType).join(' | ');
  if (schema.anyOf) return schema.anyOf.map(resolveType).join(' | ');
  return schema.type || '—';
}

function TypeBadge({ type }: { type: string }) {
  const colorMap: Record<string, string> = {
    string: 'text-[#30a46c] bg-[rgba(48,164,108,0.08)]',
    integer: 'text-[#3b82f6] bg-[rgba(59,130,246,0.08)]',
    number: 'text-[#3b82f6] bg-[rgba(59,130,246,0.08)]',
    boolean: 'text-[#e5a000] bg-[rgba(229,160,0,0.08)]',
    object: 'text-[#8b5cf6] bg-[rgba(139,92,246,0.08)]',
    array: 'text-[#e5484d] bg-[rgba(229,72,77,0.08)]',
  };
  const base = type.replace('[]', '');
  const cls = colorMap[base] || 'text-text-muted bg-bg-tertiary';
  return (
    <span className={`inline-block px-1.5 py-0.5 rounded text-[11px] font-mono font-medium ${cls}`}>
      {type}
    </span>
  );
}

function InBadge({ location }: { location: string }) {
  return (
    <span className="inline-block px-1.5 py-0.5 rounded text-[11px] font-mono text-text-muted bg-bg-tertiary">
      {location}
    </span>
  );
}

/* ===== Parameters Table ===== */

export function ParametersView({ parameters }: { parameters: unknown }) {
  const { t } = useI18n();
  if (!Array.isArray(parameters) || parameters.length === 0) return null;
  const params = parameters as Parameter[];

  return (
    <div>
      <p className="section-label mb-2">{t('dashboard.schema.parameters')}</p>
      <div className="border border-border-default rounded-lg overflow-hidden">
        <table className="w-full text-[13px]">
          <thead>
            <tr className="bg-bg-tertiary/50 text-text-muted text-[11px] uppercase tracking-wider">
              <th className="text-left px-3 py-2 font-medium">{t('dashboard.schema.name')}</th>
              <th className="text-left px-3 py-2 font-medium">{t('dashboard.schema.in')}</th>
              <th className="text-left px-3 py-2 font-medium">{t('dashboard.schema.type')}</th>
              <th className="text-left px-3 py-2 font-medium">{t('dashboard.schema.required')}</th>
              <th className="text-left px-3 py-2 font-medium">{t('dashboard.schema.descriptionCol')}</th>
            </tr>
          </thead>
          <tbody className="divide-y divide-border-muted">
            {params.map((p, i) => {
              const type = resolveType(p.schema) || p.type || '—';
              const format = p.schema?.format || p.format;
              const enumVals = p.schema?.enum || p.enum;
              return (
                <tr key={i} className="hover:bg-bg-tertiary/30 transition-colors">
                  <td className="px-3 py-2.5 font-mono text-text-primary font-medium">
                    {p.name}
                  </td>
                  <td className="px-3 py-2.5">
                    <InBadge location={p.in} />
                  </td>
                  <td className="px-3 py-2.5">
                    <div className="flex items-center gap-1.5 flex-wrap">
                      <TypeBadge type={type} />
                      {format && (
                        <span className="text-[11px] text-text-muted">({format})</span>
                      )}
                    </div>
                  </td>
                  <td className="px-3 py-2.5">
                    {p.required ? (
                      <span className="text-[11px] font-medium text-danger">{t('dashboard.schema.required')}</span>
                    ) : (
                      <span className="text-[11px] text-text-muted">{t('dashboard.schema.optional')}</span>
                    )}
                  </td>
                  <td className="px-3 py-2.5 text-text-secondary max-w-xs">
                    <div>
                      {p.description && <span>{p.description}</span>}
                      {enumVals && enumVals.length > 0 && (
                        <div className="mt-1 flex items-center gap-1 flex-wrap">
                          <span className="text-[11px] text-text-muted">{t('dashboard.schema.enum')}</span>
                          {enumVals.map((v, j) => (
                            <code key={j} className="text-[11px] font-mono bg-bg-tertiary px-1 py-0.5 rounded text-text-secondary">
                              {String(v)}
                            </code>
                          ))}
                        </div>
                      )}
                      {p.schema?.default !== undefined && (
                        <div className="mt-0.5 text-[11px] text-text-muted">
                          {t('dashboard.schema.default')} <code className="font-mono">{JSON.stringify(p.schema.default)}</code>
                        </div>
                      )}
                    </div>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
}

/* ===== Schema Properties Tree ===== */

function SchemaProperties({ schema, depth = 0 }: { schema: SchemaObj; depth?: number }) {
  const { t } = useI18n();
  const properties = schema.properties;
  const requiredSet = new Set(schema.required || []);

  if (!properties || Object.keys(properties).length === 0) {
    // Just show the type if no properties
    if (schema.type) {
      return (
        <div className="px-3 py-2 text-[13px] text-text-muted">
          <TypeBadge type={resolveType(schema)} />
          {schema.description && <span className="ml-2">{schema.description}</span>}
        </div>
      );
    }
    return null;
  }

  return (
    <div className={depth > 0 ? 'ml-4 border-l border-border-muted pl-3 mt-1' : ''}>
      {Object.entries(properties).map(([name, prop]) => {
        const type = resolveType(prop);
        const hasChildren = prop.type === 'object' && prop.properties;
        const isArray = prop.type === 'array' && prop.items?.properties;

        return (
          <div key={name} className="py-1.5 first:pt-0">
            <div className="flex items-start gap-2 text-[13px]">
              <code className="font-mono text-text-primary font-medium shrink-0">{name}</code>
              <TypeBadge type={type} />
              {prop.format && (
                <span className="text-[11px] text-text-muted">({prop.format})</span>
              )}
              {requiredSet.has(name) && (
                <span className="text-[11px] font-medium text-danger">{t('dashboard.schema.required')}</span>
              )}
              {prop.nullable && (
                <span className="text-[11px] text-text-muted">{t('dashboard.schema.nullable')}</span>
              )}
              {prop.description && (
                <span className="text-text-secondary text-[12px] leading-snug">{prop.description}</span>
              )}
            </div>
            {prop.enum && prop.enum.length > 0 && (
              <div className="ml-0 mt-0.5 flex items-center gap-1 flex-wrap">
                <span className="text-[11px] text-text-muted">{t('dashboard.schema.enum')}</span>
                {prop.enum.map((v, j) => (
                  <code key={j} className="text-[11px] font-mono bg-bg-tertiary px-1 py-0.5 rounded text-text-secondary">
                    {String(v)}
                  </code>
                ))}
              </div>
            )}
            {prop.default !== undefined && (
              <div className="text-[11px] text-text-muted mt-0.5">
                {t('dashboard.schema.default')} <code className="font-mono">{JSON.stringify(prop.default)}</code>
              </div>
            )}
            {hasChildren && <SchemaProperties schema={prop} depth={depth + 1} />}
            {isArray && prop.items && <SchemaProperties schema={prop.items} depth={depth + 1} />}
          </div>
        );
      })}
    </div>
  );
}

/* ===== Request Body ===== */

export function RequestBodyView({ requestBody }: { requestBody: unknown }) {
  const { t } = useI18n();
  if (!requestBody || typeof requestBody !== 'object') return null;
  const body = requestBody as {
    required?: boolean;
    description?: string;
    content?: Record<string, { schema?: SchemaObj }>;
    schema?: SchemaObj; // Swagger 2.0 converted format
  };

  // Swagger 2.0 format: { schema: {...} }
  if (body.schema && !body.content) {
    return (
      <div>
        <p className="section-label mb-2">
          {t('dashboard.schema.requestBody')}
          {body.required && <span className="text-danger ml-2 normal-case tracking-normal text-[11px]">{t('dashboard.schema.required')}</span>}
        </p>
        <div className="border border-border-default rounded-lg p-3">
          <SchemaProperties schema={body.schema} />
        </div>
      </div>
    );
  }

  // OpenAPI 3.x format: { content: { "application/json": { schema: {...} } } }
  if (!body.content) return null;
  const contentTypes = Object.entries(body.content);

  return (
    <div>
      <p className="section-label mb-2">
        {t('dashboard.schema.requestBody')}
        {body.required && <span className="text-danger ml-2 normal-case tracking-normal text-[11px]">{t('dashboard.schema.required')}</span>}
      </p>
      {body.description && (
        <p className="text-[13px] text-text-secondary mb-2">{body.description}</p>
      )}
      {contentTypes.map(([contentType, media]) => (
        <div key={contentType} className="border border-border-default rounded-lg overflow-hidden mb-2 last:mb-0">
          <div className="px-3 py-1.5 bg-bg-tertiary/50 border-b border-border-muted">
            <code className="text-[11px] font-mono text-text-muted">{contentType}</code>
          </div>
          <div className="p-3">
            {media.schema ? (
              media.schema.properties ? (
                <SchemaProperties schema={media.schema} />
              ) : (
                <div className="flex items-center gap-2 text-[13px]">
                  <TypeBadge type={resolveType(media.schema)} />
                  {media.schema.description && <span className="text-text-secondary">{media.schema.description}</span>}
                </div>
              )
            ) : (
              <span className="text-[13px] text-text-muted">{t('dashboard.schema.noSchema')}</span>
            )}
          </div>
        </div>
      ))}
    </div>
  );
}

/* ===== Responses ===== */

function StatusBadge({ code }: { code: string }) {
  const n = parseInt(code, 10);
  let cls = 'text-text-muted bg-bg-tertiary';
  if (n >= 200 && n < 300) cls = 'text-[#30a46c] bg-[rgba(48,164,108,0.08)]';
  else if (n >= 300 && n < 400) cls = 'text-[#3b82f6] bg-[rgba(59,130,246,0.08)]';
  else if (n >= 400 && n < 500) cls = 'text-[#e5a000] bg-[rgba(229,160,0,0.08)]';
  else if (n >= 500) cls = 'text-[#e5484d] bg-[rgba(229,72,77,0.08)]';
  return (
    <span className={`inline-block px-2 py-0.5 rounded text-[12px] font-mono font-semibold ${cls}`}>
      {code}
    </span>
  );
}

export function ResponsesView({ responses }: { responses: unknown }) {
  const { t } = useI18n();
  if (!responses || typeof responses !== 'object') return null;
  const entries = Object.entries(responses as Record<string, unknown>);
  if (entries.length === 0) return null;

  return (
    <div>
      <p className="section-label mb-2">{t('dashboard.schema.responses')}</p>
      <div className="space-y-2">
        {entries.map(([code, resp]) => {
          const response = resp as {
            description?: string;
            content?: Record<string, { schema?: SchemaObj }>;
            schema?: SchemaObj; // Swagger 2.0
          };

          // Find schema from content or direct schema (Swagger 2)
          let schema: SchemaObj | undefined;
          let contentType: string | undefined;
          if (response.content) {
            const firstEntry = Object.entries(response.content)[0];
            if (firstEntry) {
              contentType = firstEntry[0];
              schema = firstEntry[1].schema;
            }
          } else if (response.schema) {
            schema = response.schema;
          }

          return (
            <div key={code} className="border border-border-default rounded-lg overflow-hidden">
              <div className="px-3 py-2 bg-bg-tertiary/50 border-b border-border-muted flex items-center gap-2.5">
                <StatusBadge code={code} />
                {response.description && (
                  <span className="text-[13px] text-text-secondary">{response.description}</span>
                )}
                {contentType && (
                  <code className="text-[11px] font-mono text-text-muted ml-auto">{contentType}</code>
                )}
              </div>
              {schema && (schema.properties || schema.items?.properties || schema.type) && (
                <div className="p-3">
                  {schema.properties ? (
                    <SchemaProperties schema={schema} />
                  ) : schema.type === 'array' && schema.items?.properties ? (
                    <div>
                      <div className="text-[11px] text-text-muted mb-1">
                        <TypeBadge type="array" /> {t('dashboard.schema.ofObjects')}
                      </div>
                      <SchemaProperties schema={schema.items} />
                    </div>
                  ) : (
                    <div className="flex items-center gap-2 text-[13px]">
                      <TypeBadge type={resolveType(schema)} />
                      {schema.description && <span className="text-text-secondary">{schema.description}</span>}
                    </div>
                  )}
                </div>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}
