import { AppDataSource, SystemConfig, User, PlatformAccount, PublishTask } from '../models/index.js';
import type { SystemConfig as SystemConfigType } from '@media-manager/shared';
import { AVAILABLE_PLATFORM_TYPES } from '@media-manager/shared';
import { wsManager } from '../websocket/index.js';

interface UpdateConfigParams {
  allowRegistration?: boolean;
  defaultUserRole?: string;
}

export interface PublishProxyAdminConfig {
  enabled: boolean;
  cityApiUrl: string;
}

export interface UpdatePublishProxyAdminConfig {
  cityApiUrl?: string;
}

interface SystemStatus {
  database: 'connected' | 'disconnected';
  redis: 'connected' | 'disconnected';
  onlineUsers: number;
  totalUsers: number;
  totalAccounts: number;
  totalTasks: number;
  uptime: number;
}

export class SystemService {
  private configRepository = AppDataSource.getRepository(SystemConfig);
  private userRepository = AppDataSource.getRepository(User);
  private accountRepository = AppDataSource.getRepository(PlatformAccount);
  private taskRepository = AppDataSource.getRepository(PublishTask);

  async getPublicConfig(): Promise<SystemConfigType> {
    const configs = await this.configRepository.find();
    const configMap = new Map(configs.map(c => [c.configKey, c.configValue]));
    const cityApiUrl = (configMap.get('publish_proxy_city_api_url') || '').trim();

    return {
      allowRegistration: configMap.get('allow_registration') === 'true',
      defaultUserRole: configMap.get('default_user_role') || 'operator',
      maxUploadSize: 4096 * 1024 * 1024, // 4GB
      supportedPlatforms: AVAILABLE_PLATFORM_TYPES,
      publishProxy: {
        enabled: Boolean(cityApiUrl),
        provider: 'shenlong',
        cities: [],
      },
    };
  }

  async updateConfig(params: UpdateConfigParams): Promise<void> {
    if (params.allowRegistration !== undefined) {
      await this.setConfig('allow_registration', String(params.allowRegistration));
    }
    if (params.defaultUserRole) {
      await this.setConfig('default_user_role', params.defaultUserRole);
    }
  }

  async getPublishProxyAdminConfig(): Promise<PublishProxyAdminConfig> {
    const configs = await this.configRepository.find();
    const configMap = new Map(configs.map(c => [c.configKey, c.configValue]));

    const cityApiUrl = (configMap.get('publish_proxy_city_api_url') || '').trim();

    return {
      enabled: Boolean(cityApiUrl),
      cityApiUrl,
    };
  }

  async updatePublishProxyAdminConfig(params: UpdatePublishProxyAdminConfig): Promise<void> {
    if (params.cityApiUrl !== undefined) {
      await this.setConfig('publish_proxy_city_api_url', String(params.cityApiUrl || '').trim());
    }
  }

  async getPublishProxyCitiesFromApi(): Promise<string[]> {
    const configs = await this.configRepository.find({
      where: { configKey: 'publish_proxy_city_api_url' },
    });
    const cityApiUrl = (configs?.[0]?.configValue || '').trim();
    if (!cityApiUrl) return [];

    let responseText = '';
    try {
      const response = await fetch(cityApiUrl, { signal: AbortSignal.timeout(15000) });
      responseText = await response.text();
    } catch {
      return [];
    }

    try {
      const parsed = JSON.parse(responseText);
      const cities = this.extractCitiesFromProxyApiResponse(parsed);
      return Array.from(new Set(cities)).filter(Boolean).sort((a, b) => a.localeCompare(b, 'zh-CN'));
    } catch {
      return [];
    }
  }

  async getSystemStatus(): Promise<SystemStatus> {
    const [totalUsers, totalAccounts, totalTasks] = await Promise.all([
      this.userRepository.count(),
      this.accountRepository.count(),
      this.taskRepository.count(),
    ]);

    return {
      database: AppDataSource.isInitialized ? 'connected' : 'disconnected',
      redis: 'connected', // TODO: 实际检查 Redis 连接状态
      onlineUsers: wsManager.getOnlineUserCount(),
      totalUsers,
      totalAccounts,
      totalTasks,
      uptime: process.uptime(),
    };
  }

  private async setConfig(key: string, value: string): Promise<void> {
    const existing = await this.configRepository.findOne({ where: { configKey: key } });
    if (existing) {
      await this.configRepository.update(existing.id, { configValue: value });
    } else {
      await this.configRepository.save({ configKey: key, configValue: value });
    }
  }

  private extractCitiesFromProxyApiResponse(payload: any): string[] {
    const result: string[] = [];

    const pushCity = (value: any) => {
      const city = String(value || '').trim();
      if (city) result.push(city);
    };

    if (Array.isArray(payload)) {
      for (const item of payload) {
        if (typeof item === 'string') continue;
        if (item && typeof item === 'object') {
          pushCity((item as any).city ?? (item as any).name ?? (item as any).fullname);
        }
      }
      return result;
    }

    if (!payload || typeof payload !== 'object') return result;

    if (Array.isArray((payload as any).cities)) {
      for (const c of (payload as any).cities) pushCity(c);
      return result;
    }

    const data = (payload as any).data;
    if (Array.isArray(data)) {
      for (const item of data) {
        if (typeof item === 'string') continue;
        if (item && typeof item === 'object') {
          pushCity((item as any).city ?? (item as any).name ?? (item as any).fullname);
        }
      }
    }

    return result;
  }
}
