import axios, { AxiosError } from 'axios';
import type {
  User, Quota, AuthTokens, AdminStats, AdminUser, AdminUserDetail,
  AdminRecord, SystemSettings, ProfileOverview, PaginatedResponse,
  BackendTask, TeamInfo, Team, TeamDetail, TeamMember, TeamStats,
  AuditLog, AssetTeamSummary, AssetMemberSummary, AssetVideo,
  LoginAnomaly, TeamAnomalyConfig, AssetGroup, AssetItem, AssetSearchResult,
  NotificationListResponse,
} from '../types';
import { reportError } from './logCenter';

const api = axios.create({
  baseURL: '/api/v1',
  headers: { 'Content-Type': 'application/json' },
});

// Request interceptor: attach access token
api.interceptors.request.use((config) => {
  const token = localStorage.getItem('access_token');
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

// Token refresh lock: prevent concurrent refresh requests
let refreshPromise: Promise<string> | null = null;

function doRefresh(): Promise<string> {
  const refreshToken = localStorage.getItem('refresh_token');
  if (!refreshToken) return Promise.reject(new Error('no_refresh_token'));

  return axios.post('/api/v1/auth/token/refresh', { refresh: refreshToken })
    .then(({ data }) => {
      localStorage.setItem('access_token', data.access);
      if (data.refresh) {
        localStorage.setItem('refresh_token', data.refresh);
      }
      return data.access as string;
    });
}

function refreshAccessToken(): Promise<string> {
  if (refreshPromise) return refreshPromise;
  refreshPromise = doRefresh().finally(() => { refreshPromise = null; });
  return refreshPromise;
}

// Response interceptor: auto-refresh on 401
api.interceptors.response.use(
  (response) => response,
  async (error) => {
    const originalRequest = error.config;
    const requestUrl = originalRequest?.url || '';
    const authEndpoints = ['/auth/login', '/auth/register', '/auth/token/refresh'];
    const isAuthEndpoint = authEndpoints.some(ep => requestUrl.includes(ep));

    // Check special ban/kick codes on 401 or 403
    const errorCode = error.response?.data?.code || error.response?.data?.detail?.code;
    if ((error.response?.status === 401 || error.response?.status === 403) && !isAuthEndpoint) {
      if (errorCode === 'session_expired_other_device') {
        localStorage.removeItem('access_token');
        localStorage.removeItem('refresh_token');
        alert('您的账号已在其他设备登录，请重新登录');
        window.location.href = '/login';
        return Promise.reject(error);
      }
      if (errorCode === 'user_disabled') {
        localStorage.removeItem('access_token');
        localStorage.removeItem('refresh_token');
        alert('您的账号已被禁用，请联系团队管理员');
        window.location.href = '/login';
        return Promise.reject(error);
      }
      if (errorCode === 'team_disabled') {
        localStorage.removeItem('access_token');
        localStorage.removeItem('refresh_token');
        alert('您所在的团队已被禁用，请联系平台管理员');
        window.location.href = '/login';
        return Promise.reject(error);
      }
    }

    // Auto-refresh on 401 (only for non-ban cases)
    if (error.response?.status === 401 && !originalRequest._retry && !isAuthEndpoint) {
      originalRequest._retry = true;
      try {
        const newAccess = await refreshAccessToken();
        originalRequest.headers.Authorization = `Bearer ${newAccess}`;
        return api(originalRequest);
      } catch {
        localStorage.removeItem('access_token');
        localStorage.removeItem('refresh_token');
        window.location.href = '/login';
      }
    }
    // Report 5xx server errors to Log Center
    if (error.response && error.response.status >= 500) {
      reportError(error instanceof Error ? error : new Error(String(error)), {
        api_url: (error as AxiosError).config?.url,
        method: (error as AxiosError).config?.method,
        status: error.response.status,
      });
    }
    return Promise.reject(error);
  }
);

// Auth APIs
export const authApi = {
  login: (username: string, password: string) =>
    api.post<{ user: User; tokens: AuthTokens }>('/auth/login', { username, password }),

  refreshToken: (refresh: string) =>
    api.post<{ access: string; refresh?: string }>('/auth/token/refresh', { refresh }),

  getMe: () =>
    api.get<User & { quota: Quota; team: TeamInfo | null; team_disabled: boolean }>('/auth/me'),

  changePassword: (oldPassword: string, newPassword: string) =>
    api.post('/auth/change-password', { old_password: oldPassword, new_password: newPassword }),

  logout: () => api.post('/auth/logout'),
};

// Media upload API
export const mediaApi = {
  upload: (file: File) => {
    const formData = new FormData();
    formData.append('file', file);
    return api.post<{
      url: string;
      type: 'image' | 'video' | 'audio';
      filename: string;
      size: number;
    }>('/media/upload', formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
  },
};

// Video generation API
export const videoApi = {
  generate: (data: {
    prompt: string;
    mode: string;
    model: string;
    aspect_ratio: string;
    duration: number;
    resolution: string;
    references: { url: string; type: string; role: string; label: string; thumb_url?: string; duration?: string }[];
    search_mode?: string;
    seed?: number;
  }) =>
    api.post<{
      task_id: string;
      ark_task_id: string;
      status: string;
      estimated_time: number;
      seconds_consumed: number;
      error_message: string;
    }>('/video/generate', data),

  getTasks: (params?: { page_size?: number; offset?: number }) =>
    api.get<{ results: BackendTask[]; total: number; has_more: boolean }>('/video/tasks', { params }),

  getTaskStatus: (taskId: string) =>
    api.get<BackendTask>(`/video/tasks/${taskId}`),

  deleteTask: (taskId: string) =>
    api.delete(`/video/tasks/${taskId}`),

  toggleFavorite: (taskId: string) =>
    api.post<{ is_favorited: boolean }>(`/video/tasks/${taskId}/favorite`),

  getAnnouncement: () =>
    api.get<{ announcement: string; enabled: boolean; is_read: boolean; updated_at?: string }>('/announcement'),

  readAnnouncement: () =>
    api.post('/announcement/read'),
};

// Admin APIs (Super Admin)
// 公告发送(超管 fan-out 给所有用户)
export const announcementApi = {
  publish: (content: string) =>
    api.post<{ sent_to: number; message: string }>('/admin/announcement/publish', { content }),
};

export const adminApi = {
  getStats: () =>
    api.get<AdminStats>('/admin/stats'),

  // Team management
  getTeams: () =>
    api.get<{ results: Team[] }>('/admin/teams'),

  createTeam: (data: { name: string; monthly_spending_limit?: number; daily_member_limit_default?: number; expected_regions: string; markup_percentage?: number }) =>
    api.post('/admin/teams/create', data),

  getTeamDetail: (teamId: number) =>
    api.get<TeamDetail>(`/admin/teams/${teamId}`),

  updateTeam: (teamId: number, data: { name?: string; monthly_seconds_limit?: number; monthly_spending_limit?: number; daily_member_limit_default?: number; markup_percentage?: number; max_concurrent_tasks?: number; is_active?: boolean; expected_regions?: string; anomaly_config?: Partial<TeamAnomalyConfig> }) =>
    api.put(`/admin/teams/${teamId}`, data),

  topUpTeam: (teamId: number, amount: number) =>
    api.post(`/admin/teams/${teamId}/topup`, { amount }),

  setTeamPool: (teamId: number, balance: number) =>
    api.put(`/admin/teams/${teamId}/set-pool`, { balance }),

  createTeamAdmin: (teamId: number, data: { username: string; email: string; password: string }) =>
    api.post(`/admin/teams/${teamId}/admin`, data),

  setMemberRole: (teamId: number, memberId: number, isTeamAdmin: boolean) =>
    api.patch(`/admin/teams/${teamId}/members/${memberId}/role`, { is_team_admin: isTeamAdmin }),

  // 升某成员为主管(后端会自动同时设 is_team_admin=true)
  setMemberAsOwner: (teamId: number, memberId: number) =>
    api.patch(`/admin/teams/${teamId}/members/${memberId}/role`, { is_team_owner: true }),

  // User management
  createUser: (data: {
    username: string;
    email: string;
    password: string;
    daily_generation_limit?: number;
    monthly_generation_limit?: number;
    is_staff?: boolean;
  }) =>
    api.post('/admin/users/create', data),

  getUsers: (params: {
    page?: number;
    page_size?: number;
    search?: string;
    status?: string;
    team_id?: number;
  } = {}) =>
    api.get<PaginatedResponse<AdminUser>>('/admin/users', { params }),

  getUserDetail: (userId: number) =>
    api.get<AdminUserDetail>(`/admin/users/${userId}`),

  updateUserQuota: (userId: number, daily: number, monthly: number, spendingLimit?: number) =>
    api.put(`/admin/users/${userId}/quota`, {
      daily_generation_limit: daily,
      monthly_generation_limit: monthly,
      ...(spendingLimit !== undefined && { spending_limit: spendingLimit }),
    }),

  updateUserStatus: (userId: number, isActive: boolean) =>
    api.patch(`/admin/users/${userId}/status`, { is_active: isActive }),

  resetUserPassword: (userId: number, newPassword: string) =>
    api.post(`/admin/users/${userId}/reset-password`, { new_password: newPassword }),

  updateUserUsername: (userId: number, username: string) =>
    api.patch<{ user_id: number; username: string }>(`/admin/users/${userId}/username`, { username }),

  toggleUserObserver: (userId: number, isObserver: boolean) =>
    api.patch<{ user_id: number; username: string; is_observer: boolean }>(`/admin/users/${userId}/observer`, { is_observer: isObserver }),

  getRecords: (params: {
    page?: number;
    page_size?: number;
    search?: string;
    start_date?: string;
    end_date?: string;
    team_id?: number;
  } = {}) =>
    api.get<PaginatedResponse<AdminRecord>>('/admin/records', { params }),

  getSettings: () =>
    api.get<SystemSettings>('/admin/settings'),

  updateSettings: (settings: SystemSettings) =>
    api.put<SystemSettings & { updated_at: string }>('/admin/settings', settings),

  // Content Assets
  getAssetsOverview: () =>
    api.get<{
      total_videos: number;
      total_seconds: number;
      total_teams: number;
      teams: AssetTeamSummary[];
      no_team: { video_count: number; seconds_consumed: number };
    }>('/admin/assets/overview'),

  getAssetsTeamMembers: (teamId: number) =>
    api.get<{
      team_id: number;
      team_name: string;
      total_videos: number;
      total_seconds: number;
      member_count: number;
      members: AssetMemberSummary[];
    }>(`/admin/assets/team/${teamId}/members`),

  getAssetsUserVideos: (userId: number, page: number = 1, pageSize: number = 30) =>
    api.get<{
      user_id: number;
      username: string;
      total: number;
      page: number;
      page_size: number;
      results: AssetVideo[];
    }>(`/admin/assets/user/${userId}/videos`, { params: { page, page_size: pageSize } }),

  // Anomaly detection
  getLoginAnomalies: (params: {
    page?: number;
    page_size?: number;
    team_id?: number;
    rule?: string;
    level?: string;
    start_date?: string;
    end_date?: string;
  } = {}) =>
    api.get<PaginatedResponse<LoginAnomaly> & { total_pages: number }>('/admin/anomalies', { params }),

  testFeishu: (mobile: string) =>
    api.post<{ message: string }>('/admin/test-feishu', { mobile }),

  testSms: (mobile: string) =>
    api.post<{ message: string }>('/admin/test-sms', { mobile }),

  teamAutoLearn: (teamId: number, days: number = 30, minCount: number = 3) =>
    api.post<{ team_id: number; team_name: string; learned_cities: string[]; days: number; min_count: number; current_expected_regions: string }>(
      `/admin/teams/${teamId}/auto-learn`, { days, min_count: minCount }
    ),

  teamApplyLearnedRegions: (teamId: number, cities: string[]) =>
    api.post(`/admin/teams/${teamId}/apply-learned-regions`, { cities }),

  getLoginRecords: (params: {
    page?: number;
    page_size?: number;
    search?: string;
    team_id?: string;
    start_date?: string;
    end_date?: string;
    city?: string;
  } = {}) =>
    api.get('/admin/login-records', { params }),

  getAuditLogs: (params: {
    page?: number;
    page_size?: number;
    action?: string;
    operator?: string;
    start_date?: string;
    end_date?: string;
  } = {}) =>
    api.get<PaginatedResponse<AuditLog> & { total_pages: number }>('/admin/logs', { params }),
};

// Team Admin APIs
export const teamApi = {
  getInfo: () =>
    api.get<TeamInfo & { daily_member_limit_default: number; member_count: number }>('/team/info'),

  getStats: () =>
    api.get<TeamStats>('/team/stats'),

  getMembers: () =>
    api.get<{ results: TeamMember[] }>('/team/members'),

  createMember: (data: { username: string; password: string; daily_generation_limit?: number; monthly_generation_limit?: number }) =>
    api.post('/team/members/create', data),

  getMemberDetail: (memberId: number) =>
    api.get('/team/members/' + memberId),

  updateMemberQuota: (memberId: number, daily: number, monthly: number, spendingLimit?: number) =>
    api.put(`/team/members/${memberId}/quota`, {
      daily_generation_limit: daily,
      monthly_generation_limit: monthly,
      ...(spendingLimit !== undefined && { spending_limit: spendingLimit }),
    }),

  updateMemberStatus: (memberId: number, isActive: boolean) =>
    api.patch(`/team/members/${memberId}/status`, { is_active: isActive }),

  setMemberRole: (memberId: number, isTeamAdmin: boolean) =>
    api.patch(`/team/members/${memberId}/role`, { is_team_admin: isTeamAdmin }),

  resetMemberPassword: (memberId: number) =>
    api.post<{ user_id: number; username: string; new_password: string; message: string }>(`/team/members/${memberId}/reset-password`),

  updateMemberUsername: (memberId: number, username: string) =>
    api.patch<{ user_id: number; username: string }>(`/team/members/${memberId}/username`, { username }),

  // Content Assets
  getAssetsOverview: () =>
    api.get<{
      team_id: number;
      team_name: string;
      total_videos: number;
      total_seconds: number;
      member_count: number;
      members: AssetMemberSummary[];
    }>('/team/assets/overview'),

  getAssetsMemberVideos: (memberId: number, page: number = 1, pageSize: number = 30) =>
    api.get<{
      user_id: number;
      username: string;
      total: number;
      page: number;
      page_size: number;
      results: AssetVideo[];
    }>(`/team/assets/member/${memberId}/videos`, { params: { page, page_size: pageSize } }),

  // Consumption Records
  getRecords: (params: {
    page?: number;
    page_size?: number;
    search?: string;
    start_date?: string;
    end_date?: string;
  } = {}) =>
    api.get<{ total: number; page: number; page_size: number; results: AdminRecord[] }>('/team/records', { params }),
};

// Profile APIs
export const profileApi = {
  getOverview: (period: '7d' | '30d' = '7d') =>
    api.get<ProfileOverview>('/profile/overview', { params: { period } }),

  getRecords: (page: number = 1, pageSize: number = 20) =>
    api.get<PaginatedResponse<AdminRecord>>('/profile/records', {
      params: { page, page_size: pageSize },
    }),
};

export const assetsApi = {
  getGroups: (params: { page?: number; page_size?: number } = {}) =>
    api.get<{ results: AssetGroup[]; total: number }>('/assets/groups', { params }),
  createGroup: (data: FormData) =>
    api.post<AssetGroup>('/assets/groups', data, { headers: { 'Content-Type': 'multipart/form-data' } }),
  getGroupDetail: (id: number) =>
    api.get<AssetGroup & { assets: AssetItem[] }>(`/assets/groups/${id}`),
  updateGroup: (id: number, data: { name?: string; description?: string }) =>
    api.put(`/assets/groups/${id}`, data),
  deleteGroup: (id: number) =>
    api.delete(`/assets/groups/${id}`),
  addAsset: (groupId: number, data: FormData) =>
    api.post<AssetItem>(`/assets/groups/${groupId}/assets`, data, { headers: { 'Content-Type': 'multipart/form-data' } }),
  updateAsset: (id: number, data: { name: string }) =>
    api.put(`/assets/${id}`, data),
  deleteAsset: (id: number) =>
    api.delete(`/assets/${id}`),
  search: (q: string) =>
    api.get<{ results: AssetSearchResult[] }>('/assets/search', { params: { q } }),
  pollStatus: (id: number) =>
    api.get<{ id: number; status: string; url: string; error_message: string }>(`/assets/${id}/status`),
};

// In-app notifications API (站内消息)
export const notificationApi = {
  list: (params?: { unread_only?: boolean; page?: number; page_size?: number }) =>
    api.get<NotificationListResponse>('/notifications/', {
      params: {
        unread_only: params?.unread_only ? 'true' : 'false',
        page: params?.page ?? 1,
        page_size: params?.page_size ?? 20,
      },
    }),
  getUnreadCount: () =>
    api.get<{ unread_count: number }>('/notifications/unread-count'),
  markRead: (id: number) =>
    api.patch<{ id: number; is_read: boolean }>(`/notifications/${id}/read`),
  markAllRead: () =>
    api.post<{ updated: number }>('/notifications/read-all'),
};

const TOS_ORIGIN = 'https://airdrama-media.tos-cn-beijing.volces.com';
const PREVIEW_ORIGIN = 'https://airflow-play.airlabs.art';

/**
 * 把 TOS 直连域名换成 CDN 预览域名，仅用于 <video>/<audio>/<img> 等浏览器拉流场景。
 * 下载（fetch / a.href download）继续使用原 TOS 域名以避免 CDN CORS 配置依赖。
 * 非我们桶 / blob: / 已是预览域名 → 原样返回。
 */
export function rewriteTosUrl(url: string | undefined): string {
  if (!url) return '';
  if (!url.startsWith(TOS_ORIGIN)) return url;
  return PREVIEW_ORIGIN + url.slice(TOS_ORIGIN.length);
}

/**
 * Append TOS image resize parameter to reduce loading size.
 * Only applies to TOS image URLs (volces.com with image extensions).
 */
export function tosThumb(url: string | undefined, height: number): string {
  if (!url) return '';
  // 只对我们自己的 TOS 桶生效（airdrama-media），不处理火山内部桶（ark-media-asset 等）
  if (!url.includes('airdrama-media')) return url;
  if (!/\.(png|jpg|jpeg|webp|gif)/i.test(url)) return url;
  const rewritten = rewriteTosUrl(url);
  const sep = rewritten.includes('?') ? '&' : '?';
  return `${rewritten}${sep}x-tos-process=image/resize,h_${height}`;
}

export default api;
