import { invoke } from '@tauri-apps/api/core';
import type {
  ActivityEntry,
  ComponentStatus,
  LocalSingBoxConfig,
  Profile,
  ProfileInput,
  SubscriptionCache,
  SubscriptionServer,
  Target,
  TargetInput,
} from '../domain/types';

export interface CommandError {
  code: string;
  message: string;
  details?: Array<{
    field: string;
    message: string;
  }>;
}

export interface StatusResponse {
  routeLine: string;
  activeProfileCount: number;
  routedAppCount: number;
  activeTarget?: Target;
  components: ComponentStatus[];
  recentActivity: ActivityEntry[];
  generatedConfigPath: string;
}

export interface AdminStatusResponse {
  isWindows: boolean;
  isElevated: boolean;
  canRestartElevated: boolean;
  message: string;
}

export interface SavedStateResponse {
  profiles: Profile[];
  targets: Target[];
  generatedConfigPath: string;
}

export interface StartupSnapshotResponse {
  adminStatus: AdminStatusResponse;
  savedState: SavedStateResponse;
  components: ComponentStatus[];
  proxifyreSetupStatus: ProxiFyreSetupStatus;
  singboxStatus: LocalSingBoxStatusResponse;
  singboxSetupStatus: SingBoxSetupStatus;
}

export interface ProxiFyreSetupItem {
  id: string;
  name: string;
  installed: boolean;
  version?: string;
  details: string;
}

export interface ProxiFyreSetupStatus {
  ready: boolean;
  missingCount: number;
  items: ProxiFyreSetupItem[];
}

export type SingBoxSetupItem = ProxiFyreSetupItem;

export interface SingBoxSetupStatus {
  ready: boolean;
  missingCount: number;
  items: SingBoxSetupItem[];
}

export interface LocalSingBoxStatusResponse {
  config: LocalSingBoxConfig;
  cache?: SubscriptionCache;
  component: ComponentStatus;
  generatedConfigPath: string;
  lanListenHost?: string;
  subscriptionIdentity?: SubscriptionRequestIdentity;
}

export interface SubscriptionRequestIdentity {
  headers: SubscriptionRequestHeader[];
}

export interface SubscriptionRequestHeader {
  name: string;
  value: string;
}

export interface PingServerResponse {
  tag: string;
  server: string;
  serverPort: number;
  ok: boolean;
  latency?: number;
  error?: string;
}

export interface ProxyProbeResponse {
  id: string;
  name: string;
  url: string;
  ok: boolean;
  status?: number;
  latency?: number;
  ip?: string;
  error?: string;
}

export interface ProxyTargetCheckResponse {
  tag: string;
  server: string;
  serverPort: number;
  ok: boolean;
  latency?: number;
  error?: string;
  probes: ProxyProbeResponse[];
}

export interface GenerateSingBoxConfigResponse {
  success: boolean;
  message: string;
  adapterId: string;
  generatedConfigPath: string;
  selectedServerTag: string;
  listenHost: string;
  listenPort: number;
  check?: {
    checked: boolean;
    success: boolean;
    message: string;
  };
  activity: ActivityEntry;
}

export interface HelperApplyResult {
  success: boolean;
  changed: boolean;
  action: string;
  message: string;
}

export interface ApplyProfilesResponse {
  success: boolean;
  changed: boolean;
  message: string;
  adapterId: string;
  generatedConfigPath: string;
  enabledProfiles: number;
  routedApps: number;
  helper: HelperApplyResult;
  activity: ActivityEntry;
}

export function getStatus(): Promise<StatusResponse> {
  return invoke<StatusResponse>('get_status');
}

export function getAdminStatus(): Promise<AdminStatusResponse> {
  return invoke<AdminStatusResponse>('get_admin_status');
}

export function restartAsAdmin(): Promise<void> {
  return invoke<void>('restart_as_admin');
}

export function getStartupSnapshot(): Promise<StartupSnapshotResponse> {
  return invoke<StartupSnapshotResponse>('get_startup_snapshot');
}

export function getSavedState(): Promise<SavedStateResponse> {
  return invoke<SavedStateResponse>('get_saved_state');
}

export function getProfiles(): Promise<Profile[]> {
  return invoke<Profile[]>('get_profiles');
}

export function saveProfile(input: ProfileInput): Promise<Profile> {
  return invoke<Profile>('save_profile', { input });
}

export function getTargets(): Promise<Target[]> {
  return invoke<Target[]>('get_targets');
}

export function saveTarget(input: TargetInput): Promise<Target> {
  return invoke<Target>('save_target', { input });
}

export function getComponents(): Promise<ComponentStatus[]> {
  return invoke<ComponentStatus[]>('get_components');
}

export function getProxiFyreSetupStatus(): Promise<ProxiFyreSetupStatus> {
  return invoke<ProxiFyreSetupStatus>('get_proxifyre_setup_status');
}

export function getSingBoxStatus(): Promise<LocalSingBoxStatusResponse> {
  return invoke<LocalSingBoxStatusResponse>('get_singbox_status');
}

export function getSingBoxSetupStatus(): Promise<SingBoxSetupStatus> {
  return invoke<SingBoxSetupStatus>('get_singbox_setup_status');
}

export function saveSingBoxSubscription(subscriptionUrl: string): Promise<LocalSingBoxStatusResponse> {
  return invoke<LocalSingBoxStatusResponse>('save_singbox_subscription', {
    input: { subscriptionUrl },
  });
}

export function fetchSingBoxSubscription(): Promise<LocalSingBoxStatusResponse> {
  return invoke<LocalSingBoxStatusResponse>('fetch_singbox_subscription');
}

export function forgetSingBoxSubscription(): Promise<LocalSingBoxStatusResponse> {
  return invoke<LocalSingBoxStatusResponse>('forget_singbox_subscription');
}

export function selectSingBoxServer(server: SubscriptionServer): Promise<LocalSingBoxStatusResponse> {
  return invoke<LocalSingBoxStatusResponse>('select_singbox_server', {
    input: {
      tag: server.tag,
      server: server.server,
      serverPort: server.serverPort,
    },
  });
}

export function pingSingBoxServer(tag: string): Promise<PingServerResponse> {
  return invoke<PingServerResponse>('ping_singbox_server', {
    input: { tag },
  });
}

export function pingAllSingBoxServers(): Promise<PingServerResponse[]> {
  return invoke<PingServerResponse[]>('ping_all_singbox_servers');
}

export function pingProxyTarget(host: string, port: number): Promise<ProxyTargetCheckResponse> {
  return invoke<ProxyTargetCheckResponse>('ping_proxy_target', {
    input: { host, port },
  });
}

export function generateSingBoxConfig(): Promise<GenerateSingBoxConfigResponse> {
  return invoke<GenerateSingBoxConfigResponse>('generate_singbox_config');
}

export function applyProfiles(): Promise<ApplyProfilesResponse> {
  return invoke<ApplyProfilesResponse>('apply_profiles');
}

export function openConfigLocation(): Promise<string> {
  return invoke<string>('open_config_location');
}

export function startProxiFyreService(): Promise<ComponentStatus> {
  return invoke<ComponentStatus>('start_proxifyre_service');
}

export function stopProxiFyreService(): Promise<ComponentStatus> {
  return invoke<ComponentStatus>('stop_proxifyre_service');
}

export function installProxiFyre(): Promise<ComponentStatus> {
  return invoke<ComponentStatus>('install_proxifyre');
}

export function uninstallProxiFyre(): Promise<ComponentStatus> {
  return invoke<ComponentStatus>('uninstall_proxifyre');
}

export function startSingBoxService(): Promise<ComponentStatus> {
  return invoke<ComponentStatus>('start_singbox_service');
}

export function stopSingBoxService(): Promise<ComponentStatus> {
  return invoke<ComponentStatus>('stop_singbox_service');
}

export function installSingBox(): Promise<ComponentStatus> {
  return invoke<ComponentStatus>('install_singbox');
}

export function uninstallSingBox(): Promise<ComponentStatus> {
  return invoke<ComponentStatus>('uninstall_singbox');
}
