import * as plugins from './plugins.js';
import * as appstate from './appstate.js';

const SmartRouter = plugins.domtools.plugins.smartrouter.SmartRouter;

const flatViews = ['dashboard', 'settings'] as const;

const subviewMap: Record<string, readonly string[]> = {
  apps: ['app-store', 'services'] as const,
  network: ['proxy', 'domains', 'dns-records'] as const,
  registry: ['registries', 'tokens'] as const,
};

const defaultSubview: Record<string, string> = {
  apps: 'app-store',
  network: 'proxy',
  registry: 'registries',
};

const legacySubviewTargetMap: Record<string, { view: string; subview: string }> = {
  'app-store': { view: 'apps', subview: 'app-store' },
  services: { view: 'apps', subview: 'services' },
  proxy: { view: 'network', subview: 'proxy' },
  domains: { view: 'network', subview: 'domains' },
  'dns-records': { view: 'network', subview: 'dns-records' },
  registries: { view: 'registry', subview: 'registries' },
  tokens: { view: 'registry', subview: 'tokens' },
};

export const validTopLevelViews = [...flatViews, ...Object.keys(subviewMap)] as const;
export type TValidView = typeof validTopLevelViews[number];

export function isValidView(view: string): boolean {
  return (validTopLevelViews as readonly string[]).includes(view);
}

export function isValidSubview(view: string, subview: string): boolean {
  return subviewMap[view]?.includes(subview) ?? false;
}

class AppRouter {
  private router: InstanceType<typeof SmartRouter>;
  private initialized = false;
  private suppressStateUpdate = false;

  constructor() {
    this.router = new SmartRouter({ debug: false });
  }

  public init(): void {
    if (this.initialized) return;
    this.setupRoutes();
    this.setupStateSync();
    this.handleInitialRoute();
    this.initialized = true;
  }

  private setupRoutes(): void {
    for (const view of flatViews) {
      this.router.on(`/${view}`, async () => {
        this.updateViewState(view, null);
      });
    }

    for (const view of Object.keys(subviewMap)) {
      this.router.on(`/${view}`, async () => {
        this.navigateTo(`/${view}/${defaultSubview[view]}`);
      });

      for (const subview of subviewMap[view]) {
        this.router.on(`/${view}/${subview}`, async () => {
          this.updateViewState(view, subview);
        });
      }
    }

    this.router.on('/', async () => {
      this.navigateTo('/dashboard');
    });
  }

  private setupStateSync(): void {
    appstate.uiStatePart.select().subscribe((uiState: appstate.IUiState) => {
      if (this.suppressStateUpdate) return;

      const currentPath = window.location.pathname;
      const expectedPath = uiState.activeSubview
        ? `/${uiState.activeView}/${uiState.activeSubview}`
        : `/${uiState.activeView}`;

      if (currentPath !== expectedPath) {
        this.suppressStateUpdate = true;
        this.router.pushUrl(expectedPath);
        this.suppressStateUpdate = false;
      }
    });
  }

  private handleInitialRoute(): void {
    const path = window.location.pathname;

    if (!path || path === '/') {
      this.router.pushUrl('/dashboard');
      return;
    }

    const segments = path.split('/').filter(Boolean);
    const view = segments[0];
    const subview = segments[1];

    if (!isValidView(view)) {
      this.router.pushUrl('/dashboard');
      return;
    }

    if (subviewMap[view]) {
      if (subview && isValidSubview(view, subview)) {
        this.updateViewState(view, subview);
      } else {
        this.router.pushUrl(`/${view}/${defaultSubview[view]}`);
      }
    } else {
      this.updateViewState(view, null);
    }
  }

  private updateViewState(view: string, subview: string | null): void {
    this.suppressStateUpdate = true;
    const currentState = appstate.getRequiredState(appstate.uiStatePart);
    if (currentState.activeView !== view || currentState.activeSubview !== subview) {
      appstate.uiStatePart.setState({
        ...currentState,
        activeView: view,
        activeSubview: subview,
      });
    }
    this.suppressStateUpdate = false;
  }

  public navigateTo(path: string): void {
    this.router.pushUrl(path);
  }

  public navigateToView(view: string, subview?: string): void {
    const normalizedView = view.toLowerCase().replace(/\s+/g, '-');
    const normalizedSubview = subview?.toLowerCase().replace(/\s+/g, '-');

    if (!isValidView(normalizedView)) {
      const legacyTarget = legacySubviewTargetMap[normalizedView];
      if (legacyTarget) {
        this.navigateToView(legacyTarget.view, legacyTarget.subview);
        return;
      }
      this.navigateTo('/dashboard');
      return;
    }

    if (normalizedSubview && isValidSubview(normalizedView, normalizedSubview)) {
      this.navigateTo(`/${normalizedView}/${normalizedSubview}`);
    } else if (subviewMap[normalizedView]) {
      this.navigateTo(`/${normalizedView}/${defaultSubview[normalizedView]}`);
    } else {
      this.navigateTo(`/${normalizedView}`);
    }
  }

  public getCurrentView(): string {
    const uiState = appstate.getRequiredState(appstate.uiStatePart);
    return uiState.activeSubview
      ? `${uiState.activeView}/${uiState.activeSubview}`
      : uiState.activeView;
  }

  public destroy(): void {
    this.router.destroy();
    this.initialized = false;
  }
}

export const appRouter = new AppRouter();
