import type { AdminSection, AdminTaskQuery, ApiDocSection, PageKey, PlaygroundMode, WorkspaceSection, WorkspaceTaskQuery } from './types';

export interface AppRouteState {
  activePage: PageKey;
  adminSection: AdminSection;
  adminTaskQuery: AdminTaskQuery;
  apiDocSection: ApiDocSection;
  playgroundMode: PlaygroundMode;
  workspaceSection: WorkspaceSection;
  workspaceTaskQuery: WorkspaceTaskQuery;
}

export const defaultRouteState: AppRouteState = {
  activePage: 'home',
  adminSection: 'overview',
  adminTaskQuery: defaultAdminTaskQuery(),
  apiDocSection: 'openApiOverview',
  playgroundMode: 'chat',
  workspaceSection: 'overview',
  workspaceTaskQuery: defaultWorkspaceTaskQuery(),
};

const workspacePaths: Record<WorkspaceSection, string> = {
  overview: '/workspace/overview',
  billing: '/workspace/billing',
  apiKeys: '/workspace/api-keys',
  tasks: '/workspace/tasks',
  transactions: '/workspace/transactions',
};

const adminPaths: Record<AdminSection, string> = {
  overview: '/admin/overview',
  globalModels: '/admin/providers',
  baseModels: '/admin/base-models',
  pricing: '/admin/pricing',
  billingSettlements: '/admin/billing-settlements',
  platforms: '/admin/platforms',
  realtimeLoad: '/admin/realtime-load',
  tasks: '/admin/tasks',
  tenants: '/admin/tenants',
  users: '/admin/users',
  userGroups: '/admin/user-groups',
  auditLogs: '/admin/audit-logs',
  runtime: '/admin/runtime',
  systemSettings: '/admin/system-settings',
};

const docsPaths: Record<ApiDocSection, string> = {
  openApiOverview: '/docs/open-api',
  compatApiOverview: '/docs/compatible-api',
  compatGemini: '/docs/compatible-api/gemini',
  compatKling: '/docs/compatible-api/kling',
  compatVolces: '/docs/compatible-api/volces',
  compatServerMain: '/docs/compatible-api/server-main',
  guideBaseUrl: '/docs/auth',
  guideWebhook: '/docs/webhook',
  guideErrors: '/docs/errors',
  guideTesting: '/docs/testing',
  chat: '/docs/chat',
  responses: '/docs/responses',
  embeddings: '/docs/embeddings',
  reranks: '/docs/reranks',
  imageGeneration: '/docs/images/generations',
  imageEdit: '/docs/images/edits',
  videoGeneration: '/docs/videos/generations',
  asyncMode: '/docs/async',
  taskRetrieve: '/docs/tasks/retrieve',
  pricing: '/docs/pricing',
  files: '/docs/files',
};

const playgroundPaths: Record<PlaygroundMode, string> = {
  chat: '/playground/chat',
  image: '/playground/image',
  video: '/playground/video',
};

const workspaceSections = reverseMap(workspacePaths);
const adminSections = reverseMap(adminPaths);
const docsSections = reverseMap(docsPaths);
const playgroundSections = reverseMap(playgroundPaths);

export function parseAppRoute(input = currentLocationPath()): AppRouteState {
  const origin = typeof window === 'undefined' ? 'http://localhost' : window.location.origin;
  const url = new URL(input, origin);
  const path = normalizePath(url.pathname);
  const workspaceTaskQuery = parseWorkspaceTaskQuery(url.searchParams);
  const adminTaskQuery = parseAdminTaskQuery(url.searchParams);
  if (path === '/') return { ...defaultRouteState };
  if (path === '/login') return { ...defaultRouteState, activePage: 'login', workspaceTaskQuery, adminTaskQuery };
  if (path.startsWith('/playground')) {
    return { ...defaultRouteState, activePage: 'playground', playgroundMode: parsePlaygroundMode(path), workspaceTaskQuery, adminTaskQuery };
  }
  if (path === '/models') return { ...defaultRouteState, activePage: 'models', workspaceTaskQuery, adminTaskQuery };
  if (path.startsWith('/workspace')) {
    return { ...defaultRouteState, activePage: 'workspace', workspaceSection: parseWorkspaceSection(path), workspaceTaskQuery, adminTaskQuery };
  }
  if (path.startsWith('/admin')) {
    return { ...defaultRouteState, activePage: 'admin', adminSection: parseAdminSection(path), workspaceTaskQuery, adminTaskQuery };
  }
  if (path.startsWith('/docs')) {
    return { ...defaultRouteState, activePage: 'docs', apiDocSection: parseDocSection(path), workspaceTaskQuery, adminTaskQuery };
  }
  return { ...defaultRouteState };
}

function currentLocationPath() {
  if (typeof window === 'undefined') return '/';
  return `${window.location.pathname}${window.location.search}`;
}

export function pathForPage(page: PageKey, route: AppRouteState): string {
  if (page === 'playground') return pathForPlaygroundMode(route.playgroundMode);
  if (page === 'models') return '/models';
  if (page === 'workspace') return pathForWorkspaceSection(route.workspaceSection);
  if (page === 'admin') return pathForAdminSection(route.adminSection);
  if (page === 'docs') return pathForApiDocSection(route.apiDocSection);
  if (page === 'login') return '/login';
  return '/';
}

export function pathForWorkspaceSection(section: WorkspaceSection) {
  return workspacePaths[section] ?? workspacePaths.overview;
}

export function pathForWorkspaceTaskQuery(query: WorkspaceTaskQuery) {
  const normalized = normalizeWorkspaceTaskQuery(query);
  const search = new URLSearchParams();
  if (normalized.query) search.set('q', normalized.query);
  if (normalized.modelType) search.set('type', normalized.modelType);
  if (normalized.createdFrom) search.set('from', normalized.createdFrom);
  if (normalized.createdTo) search.set('to', normalized.createdTo);
  if (normalized.page !== 1) search.set('page', String(normalized.page));
  if (normalized.pageSize !== 10) search.set('pageSize', String(normalized.pageSize));
  const suffix = search.toString();
  return `${workspacePaths.tasks}${suffix ? `?${suffix}` : ''}`;
}

export function pathForAdminTaskQuery(query: AdminTaskQuery) {
  const normalized = normalizeAdminTaskQuery(query);
  const search = new URLSearchParams();
  if (normalized.query) search.set('q', normalized.query);
  if (normalized.tenantId) search.set('tenantId', normalized.tenantId);
  if (normalized.userId) search.set('userId', normalized.userId);
  if (normalized.userGroupId) search.set('userGroupId', normalized.userGroupId);
  if (normalized.status) search.set('status', normalized.status);
  if (normalized.platformId) search.set('platformId', normalized.platformId);
  if (normalized.model) search.set('model', normalized.model);
  if (normalized.modelType) search.set('modelType', normalized.modelType);
  if (normalized.runMode) search.set('runMode', normalized.runMode);
  if (normalized.billingStatus) search.set('billingStatus', normalized.billingStatus);
  if (normalized.apiKey) search.set('apiKey', normalized.apiKey);
  if (normalized.createdFrom) search.set('createdFrom', normalized.createdFrom);
  if (normalized.createdTo) search.set('createdTo', normalized.createdTo);
  if (normalized.page !== 1) search.set('page', String(normalized.page));
  if (normalized.pageSize !== 20) search.set('pageSize', String(normalized.pageSize));
  const suffix = search.toString();
  return `${adminPaths.tasks}${suffix ? `?${suffix}` : ''}`;
}

export function pathForAdminSection(section: AdminSection) {
  return adminPaths[section] ?? adminPaths.overview;
}

export function pathForApiDocSection(section: ApiDocSection) {
  return docsPaths[section] ?? docsPaths.openApiOverview;
}

export function pathForPlaygroundMode(mode: PlaygroundMode) {
  return playgroundPaths[mode] ?? playgroundPaths.chat;
}

function parseWorkspaceSection(path: string): WorkspaceSection {
  return workspaceSections[path] ?? (path === '/workspace' ? 'overview' : 'overview');
}

function parseAdminSection(path: string): AdminSection {
  if (path === '/admin') return 'overview';
  if (path === '/admin/models/global') return 'baseModels';
  if (path === '/admin/usergroups') return 'userGroups';
  if (path === '/admin/access-rules') return 'userGroups';
  return adminSections[path] ?? 'overview';
}

function parseDocSection(path: string): ApiDocSection {
  if (path === '/docs') return 'openApiOverview';
  if (path === '/docs/playground') return 'guideTesting';
  if (path === '/docs/api/chat') return 'chat';
  if (path === '/docs/api/responses') return 'responses';
  if (path === '/docs/api/embeddings') return 'embeddings';
  if (path === '/docs/api/reranks') return 'reranks';
  if (path === '/docs/api/media') return 'imageGeneration';
  if (path === '/docs/api/videos') return 'videoGeneration';
  if (path === '/docs/api/tasks') return 'taskRetrieve';
  return docsSections[path] ?? 'openApiOverview';
}

function parsePlaygroundMode(path: string): PlaygroundMode {
  if (path === '/playground') return 'chat';
  return playgroundSections[path] ?? 'chat';
}

function normalizePath(pathname: string) {
  const path = pathname.replace(/\/+$/, '');
  return path || '/';
}

function reverseMap<T extends string>(value: Record<T, string>) {
  return Object.fromEntries(Object.entries(value).map(([key, path]) => [path, key])) as Record<string, T>;
}

export function defaultWorkspaceTaskQuery(): WorkspaceTaskQuery {
  return {
    query: '',
    modelType: '',
    createdFrom: '',
    createdTo: '',
    page: 1,
    pageSize: 10,
  };
}

export function normalizeWorkspaceTaskQuery(query: WorkspaceTaskQuery): WorkspaceTaskQuery {
  return {
    query: query.query.trim(),
    modelType: query.modelType.trim(),
    createdFrom: query.createdFrom.trim(),
    createdTo: query.createdTo.trim(),
    page: positiveInt(query.page, 1),
    pageSize: clampPageSize(query.pageSize),
  };
}

export function workspaceTaskQueryKey(query: WorkspaceTaskQuery) {
  const normalized = normalizeWorkspaceTaskQuery(query);
  return JSON.stringify(normalized);
}

export function defaultAdminTaskQuery(): AdminTaskQuery {
  return {
    query: '',
    tenantId: '',
    userId: '',
    userGroupId: '',
    status: '',
    platformId: '',
    model: '',
    modelType: '',
    runMode: '',
    billingStatus: '',
    apiKey: '',
    createdFrom: '',
    createdTo: '',
    page: 1,
    pageSize: 20,
  };
}

export function normalizeAdminTaskQuery(query: AdminTaskQuery): AdminTaskQuery {
  return {
    query: query.query.trim(),
    tenantId: query.tenantId.trim(),
    userId: query.userId.trim(),
    userGroupId: query.userGroupId.trim(),
    status: query.status.trim(),
    platformId: query.platformId.trim(),
    model: query.model.trim(),
    modelType: query.modelType.trim(),
    runMode: query.runMode.trim(),
    billingStatus: query.billingStatus.trim(),
    apiKey: query.apiKey.trim(),
    createdFrom: query.createdFrom.trim(),
    createdTo: query.createdTo.trim(),
    page: positiveInt(query.page, 1),
    pageSize: Math.min(100, Math.max(1, positiveInt(query.pageSize, 20))),
  };
}

export function adminTaskQueryKey(query: AdminTaskQuery) {
  return JSON.stringify(normalizeAdminTaskQuery(query));
}

function parseAdminTaskQuery(search: URLSearchParams): AdminTaskQuery {
  return normalizeAdminTaskQuery({
    query: search.get('q') ?? search.get('query') ?? '',
    tenantId: search.get('tenantId') ?? '',
    userId: search.get('userId') ?? '',
    userGroupId: search.get('userGroupId') ?? '',
    status: search.get('status') ?? '',
    platformId: search.get('platformId') ?? '',
    model: search.get('model') ?? '',
    modelType: search.get('modelType') ?? '',
    runMode: search.get('runMode') ?? '',
    billingStatus: search.get('billingStatus') ?? '',
    apiKey: search.get('apiKey') ?? '',
    createdFrom: search.get('createdFrom') ?? search.get('from') ?? '',
    createdTo: search.get('createdTo') ?? search.get('to') ?? '',
    page: Number(search.get('page') ?? 1),
    pageSize: Number(search.get('pageSize') ?? 20),
  });
}

function parseWorkspaceTaskQuery(search: URLSearchParams): WorkspaceTaskQuery {
  return normalizeWorkspaceTaskQuery({
    query: search.get('q') ?? search.get('query') ?? '',
    modelType: search.get('type') ?? search.get('modelType') ?? '',
    createdFrom: search.get('from') ?? search.get('createdFrom') ?? '',
    createdTo: search.get('to') ?? search.get('createdTo') ?? '',
    page: Number(search.get('page') ?? 1),
    pageSize: Number(search.get('pageSize') ?? search.get('limit') ?? 10),
  });
}

function positiveInt(value: number, fallback: number) {
  return Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
}

function clampPageSize(value: number) {
  const normalized = positiveInt(value, 10);
  return Math.min(100, Math.max(1, normalized));
}
