import * as plugins from '../plugins.js';
import * as appstate from '../appstate.js';
import * as interfaces from '../../dist_ts_interfaces/index.js';
import { appRouter } from '../router.js';
import {
  DeesElement,
  css,
  cssManager,
  customElement,
  html,
  state,
  type TemplateResult
} from '@design.estate/dees-element';

// Import view components
import { OpsViewOverview } from './ops-view-overview.js';
import { OpsViewNetwork } from './ops-view-network.js';
import { OpsViewEmails } from './ops-view-emails.js';
import { OpsViewLogs } from './ops-view-logs.js';
import { OpsViewConfig } from './ops-view-config.js';
import { OpsViewRoutes } from './ops-view-routes.js';
import { OpsViewApiTokens } from './ops-view-apitokens.js';
import { OpsViewSecurity } from './ops-view-security.js';
import { OpsViewCertificates } from './ops-view-certificates.js';
import { OpsViewRemoteIngress } from './ops-view-remoteingress.js';
import { OpsViewVpn } from './ops-view-vpn.js';
import { OpsViewSecurityProfiles } from './ops-view-securityprofiles.js';
import { OpsViewNetworkTargets } from './ops-view-networktargets.js';

@customElement('ops-dashboard')
export class OpsDashboard extends DeesElement {
  @state() accessor loginState: appstate.ILoginState = {
    identity: null,
    isLoggedIn: false,
  };

  @state() accessor uiState: appstate.IUiState = {
    activeView: 'overview',
    sidebarCollapsed: false,
    autoRefresh: true,
    refreshInterval: 1000,
    theme: 'light',
  };

  @state() accessor configState: appstate.IConfigState = {
    config: null,
    isLoading: false,
    error: null,
  };

  // Store viewTabs as a property to maintain object references
  private viewTabs = [
    {
      name: 'Overview',
      iconName: 'lucide:layoutDashboard',
      element: OpsViewOverview,
    },
    {
      name: 'Configuration',
      iconName: 'lucide:settings',
      element: OpsViewConfig,
    },
    {
      name: 'Network',
      iconName: 'lucide:network',
      element: OpsViewNetwork,
    },
    {
      name: 'Emails',
      iconName: 'lucide:mail',
      element: OpsViewEmails,
    },
    {
      name: 'Logs',
      iconName: 'lucide:scrollText',
      element: OpsViewLogs,
    },
    {
      name: 'Routes',
      iconName: 'lucide:route',
      element: OpsViewRoutes,
    },
    {
      name: 'SecurityProfiles',
      iconName: 'lucide:shieldCheck',
      element: OpsViewSecurityProfiles,
    },
    {
      name: 'NetworkTargets',
      iconName: 'lucide:server',
      element: OpsViewNetworkTargets,
    },
    {
      name: 'ApiTokens',
      iconName: 'lucide:key',
      element: OpsViewApiTokens,
    },
    {
      name: 'Security',
      iconName: 'lucide:shield',
      element: OpsViewSecurity,
    },
    {
      name: 'Certificates',
      iconName: 'lucide:badgeCheck',
      element: OpsViewCertificates,
    },
    {
      name: 'RemoteIngress',
      iconName: 'lucide:globe',
      element: OpsViewRemoteIngress,
    },
    {
      name: 'VPN',
      iconName: 'lucide:shield',
      element: OpsViewVpn,
    },
  ];

  private get globalMessages() {
    const messages: Array<{ id: string; type: string; message: string; dismissible?: boolean }> = [];
    const config = this.configState.config;
    if (config && !config.cache.enabled) {
      messages.push({
        id: 'db-disabled',
        type: 'warning',
        message: 'Database is disabled. Creating and editing routes, profiles, targets, and API tokens is not available.',
        dismissible: false,
      });
    }
    return messages;
  }

  /**
   * Get the current view tab based on the UI state's activeView.
   * Used to pass the correct selectedView to dees-simple-appdash on initial render.
   */
  private get currentViewTab() {
    return this.viewTabs.find(t => t.name.toLowerCase() === this.uiState.activeView) || this.viewTabs[0];
  }

  constructor() {
    super();
    document.title = 'DCRouter OpsServer';
    
    // Subscribe to login state
    const loginSubscription = appstate.loginStatePart
      .select((stateArg) => stateArg)
      .subscribe((loginState) => {
        this.loginState = loginState;
        // Trigger data fetch when logged in
        if (loginState.isLoggedIn) {
          appstate.statsStatePart.dispatchAction(appstate.fetchAllStatsAction, null);
          appstate.configStatePart.dispatchAction(appstate.fetchConfigurationAction, null);
        }
      });
    this.rxSubscriptions.push(loginSubscription);
    
    // Subscribe to config state (for global warnings)
    const configSubscription = appstate.configStatePart
      .select((stateArg) => stateArg)
      .subscribe((configState) => {
        this.configState = configState;
      });
    this.rxSubscriptions.push(configSubscription);

    // Subscribe to UI state
    const uiSubscription = appstate.uiStatePart
      .select((stateArg) => stateArg)
      .subscribe((uiState) => {
        this.uiState = uiState;
        // Sync appdash view when state changes (e.g., from URL navigation)
        this.syncAppdashView(uiState.activeView);
      });
    this.rxSubscriptions.push(uiSubscription);
  }

  /**
   * Sync the dees-simple-appdash view selection with the current state.
   * This is needed when the URL changes and we need to update the UI.
   */
  private syncAppdashView(viewName: string): void {
    const appDash = this.shadowRoot?.querySelector('dees-simple-appdash') as any;
    if (!appDash) return;

    const targetTab = this.viewTabs.find(t => t.name.toLowerCase() === viewName);
    if (!targetTab) return;

    // Check if we need to switch (avoid unnecessary updates)
    if (appDash.selectedView === targetTab) return;

    // Update the selected view programmatically
    appDash.selectedView = targetTab;

    // Update the displayed content
    const content = appDash.shadowRoot?.querySelector('.appcontent');
    if (content) {
      if (appDash.currentView) {
        appDash.currentView.remove();
      }
      const view = new targetTab.element();
      content.appendChild(view);
      appDash.currentView = view;
    }
  }

  public static styles = [
    cssManager.defaultStyles,
    css`
      :host {
        display: block;
        width: 100%;
        height: 100vh;
        overflow: hidden;
      }

      .maincontainer {
        position: relative;
        width: 100%;
        height: 100%;
      }
    `,
  ];

  public render(): TemplateResult {
    return html`
      <div class="maincontainer">
        <dees-simple-login
          name="DCRouter OpsServer"
        >
          <dees-simple-appdash
            name="DCRouter OpsServer"
            .viewTabs=${this.viewTabs}
            .selectedView=${this.currentViewTab}
            .globalMessages=${this.globalMessages}
          >
          </dees-simple-appdash>
        </dees-simple-login>
      </div>
    `;
  }

  public async firstUpdated() {
    const simpleLogin = this.shadowRoot!.querySelector('dees-simple-login') as any;
    simpleLogin.addEventListener('login', (e: Event) => {
      // Handle logout event
      const detail = (e as CustomEvent).detail;
      this.login(detail.data.username, detail.data.password);
    });

    // Handle view changes
    const appDash = this.shadowRoot!.querySelector('dees-simple-appdash');
    if (appDash) {
      appDash.addEventListener('view-select', (e: Event) => {
        const viewName = (e as CustomEvent).detail.view.name.toLowerCase();
        // Use router for navigation instead of direct state update
        appRouter.navigateToView(viewName);
      });

      // Handle logout event
      appDash.addEventListener('logout', async () => {
        await appstate.loginStatePart.dispatchAction(appstate.logoutAction, null);
      });
    }

    // Handle initial state - check if we have a stored session that's still valid
    const loginState = appstate.loginStatePart.getState()!;
    if (loginState.identity?.jwt) {
      if (loginState.identity.expiresAt > Date.now()) {
        // Client-side expiry looks valid — verify with server (keypair may have changed)
        try {
          const verifyRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
            interfaces.requests.IReq_VerifyIdentity
          >('/typedrequest', 'verifyIdentity');
          const response = await verifyRequest.fire({ identity: loginState.identity });
          if (response.valid) {
            // JWT confirmed valid by server
            this.loginState = loginState;
            await (simpleLogin as any).switchToSlottedContent();
            await appstate.statsStatePart.dispatchAction(appstate.fetchAllStatsAction, null);
            await appstate.configStatePart.dispatchAction(appstate.fetchConfigurationAction, null);
          } else {
            // Server rejected the JWT — clear state, show login
            await appstate.loginStatePart.dispatchAction(appstate.logoutAction, null);
          }
        } catch {
          // Server unreachable or error — clear state, show login
          await appstate.loginStatePart.dispatchAction(appstate.logoutAction, null);
        }
      } else {
        // JWT expired, clear the stored state
        await appstate.loginStatePart.dispatchAction(appstate.logoutAction, null);
      }
    }
  }

  private async login(username: string, password: string) {
    const domtools = await this.domtoolsPromise;
    console.log(`Attempting to login...`);
    const simpleLogin = this.shadowRoot!.querySelector('dees-simple-login') as any;
    const form = simpleLogin.shadowRoot!.querySelector('dees-form') as any;
    form.setStatus('pending', 'Logging in...');
    
    const state = await appstate.loginStatePart.dispatchAction(appstate.loginAction, {
      username,
      password,
    });
    
    if (state.identity) {
      console.log('Login successful');
      this.loginState = state;
      form!.setStatus('success', 'Logged in!');
      await simpleLogin!.switchToSlottedContent();
      await appstate.statsStatePart.dispatchAction(appstate.fetchAllStatsAction, null);
      await appstate.configStatePart.dispatchAction(appstate.fetchConfigurationAction, null);
    } else {
      form!.setStatus('error', 'Login failed!');
      await domtools.convenience.smartdelay.delayFor(2000);
      form!.reset();
    }
  }
}