import http from "@/api/http";

export interface CreativeStyle {
  id: string;
  name: string;
  image_url?: string;
  reference_image_asset_id?: string;
  reference_image_url?: string;
}
export interface VideoReferenceCapability {
  supported: boolean;
  max_count: number;
  min_total_duration_ms?: number;
  max_total_duration_ms?: number;
  min_short_side_pixels?: number;
  max_short_side_pixels?: number;
}
export interface VideoModelCapabilities {
  reference_images: VideoReferenceCapability;
  reference_audios: VideoReferenceCapability;
  reference_videos: VideoReferenceCapability;
}
export interface CreativeModel {
  id: string;
  name: string;
  model_type: "text" | "image" | "video";
  channel_name: string;
  multimodal?: boolean;
  text_billing_mode?: "per_request" | "per_token";
  capabilities?: VideoModelCapabilities;
}
export interface CreativePrice {
  model_id: string;
  price_key: string;
  unit: string;
  price: number;
}
export interface CreativeOptions {
  styles: CreativeStyle[];
  models: CreativeModel[];
  prices?: CreativePrice[];
}
export interface PromptPreset {
  id: string;
  name: string;
  type: string;
  content: string;
  scope?: "system" | "user";
  editable?: boolean;
}
export interface ModelConfig {
  purpose: string;
  model_id: string;
  model_name: string;
  model_type: "text" | "image" | "video";
  channel_name: string;
  settings?: { aspect_ratio?: string; resolution?: string; prompt?: string };
  capabilities?: VideoModelCapabilities;
}
export interface ProjectSummary {
  id: string;
  name: string;
  project_type: string;
  style_name: string;
  era_type: string;
  custom_era?: string;
  aspect_ratio: string;
  localization: string;
  short_drama_type?: string;
  play_count?: string;
  audience_profile?: string;
  producer?: string;
  cast_members: ProjectCastMember[];
  cover_url?: string;
  cover_mime_type?: string;
  cover_video_url?: string;
  episode_count: number;
  processing_count: number;
  updated_at: string;
}

export interface ProjectCastMember {
  name: string;
  follower_count?: string;
}

/** 剧集摘要，包含项目列表和工作台所需的处理状态与产出标记。 */
export interface Episode {
  id: string;
  episode_no: number;
  name: string;
  audio_source: "video_audio" | "subtitle_file";
  source_language?: string;
  status: string;
  analysis_message?: string;
  source_video_asset_id?: string;
  source_video_url?: string;
  source_video_original_name?: string;
  subtitle_asset_id?: string;
  subtitle_original_name?: string;
  cover_url?: string;
  cover_video_url?: string;
  storyboard_count: number;
  completed_storyboard_count: number;
  has_redraw_script?: boolean;
  has_text_source?: boolean;
  updated_at?: string;
}

export interface ProjectDetail extends ProjectSummary {
  style_id: string;
  style_image_url?: string;
  model_configs: ModelConfig[];
  episodes: Episode[];
}

export interface ProjectAsset {
  id: string;
  project_id: string;
  source_episode_id?: string;
  asset_type: "character" | "scene" | "prop" | "custom";
  name: string;
  description?: string;
  image_prompt?: string;
  appearances?: unknown[];
  image_asset_id?: string;
  audio_asset_id?: string;
  audio_duration_ms?: number;
  image_url?: string;
  audio_url?: string;
  video_url?: string;
  user_edited: boolean;
}

export interface Storyboard {
  id: string;
  episode_id: string;
  sequence_no: number;
  start_ms: number;
  end_ms: number;
  duration_seconds: number;
  title?: string;
  thumbnail_asset_id?: string;
  thumbnail_url?: string;
  script_content?: string;
  source_excerpt?: string;
  prompt_content?: string;
  image_prompt?: string;
  dialogue?: unknown[];
  asset_refs?: Array<{ id: string; name?: string }>;
  locked: boolean;
  active_output_id?: string;
  status: string;
  output_id?: string;
  result_media_id?: string;
  result_url?: string;
  result_mime?: string;
  history_count: number;
  task_status?: string;
}

export interface WorkbenchData {
  project: ProjectDetail;
  episode: Episode;
  assets: ProjectAsset[];
  storyboards: Storyboard[];
}
export interface RedrawSource {
  source_video_asset_id?: string;
  source_video_url?: string;
  source_video_original_name?: string;
  subtitle_asset_id?: string;
  subtitle_url?: string;
  subtitle_original_name?: string;
  audio_source: "video_audio" | "subtitle_file";
  source_language?: string;
  status: string;
  analysis_message?: string;
}
export interface RedrawWorkbenchData {
  project: ProjectDetail;
  episode: Episode;
  source: RedrawSource;
  assets: ProjectAsset[];
  storyboards: Storyboard[];
  script_content: string;
}
export interface DramaChapterPreview {
  title: string;
  char_count: number;
}
export interface DramaImportPreview {
  import_token: string;
  has_chapters: boolean;
  total_characters: number;
  chapters: DramaChapterPreview[];
  single_episode_confirmation_required: boolean;
}
export interface DramaEpisodeSource {
  id: string;
  episode_id: string;
  title?: string;
  raw_content: string;
  char_count: number;
  source_type: string;
  source_filename?: string;
  content_sha256: string;
}
export interface DramaParseTask {
  id: string;
  request_id: string;
  batch_id?: string;
  episode_id: string;
  status: string;
  input_tokens?: number;
  output_tokens?: number;
  total_tokens?: number;
  estimated_points?: string;
  prepaid_points?: string;
  actual_points?: string;
  cost_refunded?: boolean;
  token_count_source?: string;
  error_code?: string;
  error_message?: string;
  created_at: string;
  finished_at?: string;
}
export interface GenerationTask {
  id: string;
  request_id: string;
  task_type: string;
  status: string;
  episode_id?: string;
  storyboard_id?: string;
  mode?: string;
  phase_started_at?: string;
  sequence_no?: number;
  asset_id?: string;
  estimated_points?: string;
  actual_points?: string;
  error_code?: string;
  error_message?: string;
  result_url?: string;
  created_at: string;
  submitted_at?: string;
  finished_at?: string;
  last_result_at?: string;
}
export interface GenerationOutput {
  id: string;
  task_id: string;
  media_asset_id: string;
  output_type: string;
  public_url: string;
  mime_type: string;
  size_bytes: number;
  estimated_points?: string;
  actual_points?: string;
  active: boolean;
  candidate?: boolean;
  created_at: string;
}
export interface ProjectPayload {
  project_type?: "video_redraw" | "premium_drama";
  name: string;
  style_id: string;
  era_type: string;
  custom_era?: string | null;
  aspect_ratio: string;
  localization?: string | null;
  short_drama_type?: string;
  play_count?: string;
  audience_profile?: string;
  producer?: string;
  cast_members?: ProjectCastMember[];
}
export interface ScriptAnalysis {
  id: string;
  user_id: string;
  name: string;
  source_content: string;
  result_content: string;
  analysis_result: ScriptAnalysisResult;
  analysis_status: "idle" | "queued" | "running" | "succeeded" | "failed";
  analysis_message?: string;
  characters?: ScriptAnalysisCharacter[];
  created_at: string;
  updated_at: string;
}
export interface ScriptAnalysisImportProject {
  id: string;
  name: string;
  episode_count: number;
  char_count: number;
  updated_at: string;
}
export interface ScriptAnalysisCharacter {
  id: string;
  script_analysis_id: string;
  name: string;
  faction: "正派" | "反派" | "中立派";
  biography: string;
  motivation: string;
  relationship: string;
  sort_order: number;
}
export interface ScriptAnalysisResult {
  tags?: { drama_tags?: string[]; applicable_scene_tags?: string[] };
  selling_point?: { summary?: string; highlights?: Array<{ type: string; content: string }> };
  story_structure?: {
    synopsis?: string;
    story_outline?: string[];
    emotion_outline?: Array<{ stage: string; emotion: string; description: string }>;
    episode_outlines?: Array<{ episode_no: number; title: string; outline: string; emotion: string }>;
    characters?: Array<{
      name: string;
      faction: "正派" | "反派" | "中立派";
      biography: string;
      motivation: string;
      relationship: string;
    }>;
  };
  opening_hook?: {
    first_scene?: string;
    first_line?: string;
    attention_methods?: string[];
    analysis?: string;
    optimization?: string;
  };
  episode_hooks?: Array<{ episode_no: number; hook_type: string; hook: string; basis: string }>;
  episode_10_paywall_hooks?: Array<{ hook_type: string; content: string; appeal: string }>;
  custom_analysis?: Array<{ objective: string; conclusion: string; evidence: string[] }>;
  unmatched_objectives?: Array<{ objective: string; reason: string }>;
}

const data = <T>(response: { data: { data: T } }) => response.data.data;

export const creativeApi = {
  options: () => http.get("/creative/options").then(data<CreativeOptions>),
  allProjects: () => http.get("/projects").then(data<ProjectSummary[]>),
  projects: (keyword = "") =>
    http.get("/projects", { params: { project_type: "video_redraw", keyword } }).then(data<ProjectSummary[]>),
  dramaProjects: (keyword = "") =>
    http.get("/projects", { params: { project_type: "premium_drama", keyword } }).then(data<ProjectSummary[]>),
  createProject: (payload: ProjectPayload) => http.post("/projects", payload).then(data<{ id: string }>),
  project: (projectId: string) => http.get(`/projects/${projectId}`).then(data<ProjectDetail>),
  updateProject: (projectId: string, payload: ProjectPayload) => http.put(`/projects/${projectId}`, payload),
  deleteProject: (projectId: string) => http.delete(`/projects/${projectId}`),
  saveModels: (projectId: string, payload: Record<string, unknown>) =>
    http.put(`/projects/${projectId}/model-configs`, payload),
  promptPresets: (type: string) =>
    http.get(`/user/prompts/${encodeURIComponent(type)}`).then(data<{ prompts: PromptPreset[]; selected_id?: string }>),
  selectPrompt: (type: string, promptId?: string) =>
    http.put(`/user/prompts/${encodeURIComponent(type)}/select`, { prompt_id: promptId || null }),
  createCustomPrompt: (payload: { name: string; type: string; content: string }) =>
    http.post("/user/custom-prompts", payload).then(data<PromptPreset>),
  updateCustomPrompt: (id: string, payload: { name: string; type?: string; content: string }) =>
    http.put(`/user/custom-prompts/${id}`, payload).then(data<PromptPreset>),
  deleteCustomPrompt: (id: string) => http.delete(`/user/custom-prompts/${id}`),
  createEpisode: (projectId: string, payload: { episode_no?: number; name?: string } = {}) =>
    http.post(`/projects/${projectId}/episodes`, payload).then(data<Episode>),
  updateEpisodeName: (projectId: string, episodeId: string, name: string) =>
    http.put(`/projects/${projectId}/episodes/${episodeId}`, { name }).then(data<Episode>),
  previewDramaImport: (projectId: string, payload: { file?: File; rawText?: string }) => {
    const form = new FormData();
    if (payload.file) form.append("file", payload.file);
    if (payload.rawText) form.append("raw_text", payload.rawText);
    return http
      .post(`/projects/${projectId}/episodes/import/preview`, form, {
        timeout: 0,
        headers: { "Content-Type": "multipart/form-data" },
      })
      .then(data<DramaImportPreview>);
  },
  confirmDramaImport: (
    projectId: string,
    payload: {
      import_token: string;
      chapters_per_episode: number;
      start_episode_no: number;
      treat_as_single_episode: boolean;
    },
  ) => http.post(`/projects/${projectId}/episodes/import/confirm`, payload).then(data<Episode[]>),
  dramaEpisodeSource: (projectId: string, episodeId: string) =>
    http.get(`/projects/${projectId}/episodes/${episodeId}/text-source`).then(data<DramaEpisodeSource>),
  saveDramaEpisodeSource: (projectId: string, episodeId: string, payload: { title?: string; raw_content: string }) =>
    http.put(`/projects/${projectId}/episodes/${episodeId}/text-source`, payload).then(data<DramaEpisodeSource>),
  parseDramaEpisode: (projectId: string, episodeId: string) =>
    http.post(`/projects/${projectId}/episodes/${episodeId}/parse`).then(data<DramaParseTask>),
  reparseDramaEpisode: (projectId: string, episodeId: string) =>
    http.post(`/projects/${projectId}/episodes/${episodeId}/reparse`).then(data<DramaParseTask>),
  createDramaStoryboard: (projectId: string, episodeId: string) =>
    http.post(`/projects/${projectId}/episodes/${episodeId}/storyboards`).then(data<Storyboard>),
  dramaParseTasks: (projectId: string, episodeId?: string) =>
    http.get(`/projects/${projectId}/parse-tasks`, { params: { episode_id: episodeId } }).then(data<DramaParseTask[]>),
  cancelDramaParse: (projectId: string, taskId: string) =>
    http.post(`/projects/${projectId}/parse-tasks/${taskId}/cancel`),
  deleteEpisode: (projectId: string, episodeId: string) => http.delete(`/projects/${projectId}/episodes/${episodeId}`),
  workbench: (projectId: string, episodeId: string) =>
    http.get(`/projects/${projectId}/episodes/${episodeId}/workbench`).then(data<WorkbenchData>),
  // episodeVideosArchive 下载当前剧集按项目类型筛选后的全部视频 ZIP。
  episodeVideosArchive: (projectId: string, episodeId: string) =>
    http
      .get(`/projects/${projectId}/episodes/${episodeId}/videos.zip`, { responseType: "blob", timeout: 0 })
      .then((response) => response.data as Blob),
  redrawWorkbench: (projectId: string, episodeId: string) =>
    http.get(`/projects/${projectId}/episodes/${episodeId}/redraw-workbench`).then(data<RedrawWorkbenchData>),
  uploadSource: (projectId: string, episodeId: string, file: File) =>
    upload(`/projects/${projectId}/episodes/${episodeId}/source`, file),
  uploadSubtitle: (projectId: string, episodeId: string, file: File) =>
    upload(`/projects/${projectId}/episodes/${episodeId}/subtitle`, file),
  uploadRedrawSource: (projectId: string, file: File) => upload(`/projects/${projectId}/redraw-source`, file),
  uploadRedrawSubtitle: (projectId: string, file: File) => upload(`/projects/${projectId}/redraw-subtitle`, file),
  saveAnalysisSettings: (
    projectId: string,
    episodeId: string,
    payload: { audio_source: string; source_language: string },
  ) => http.put(`/projects/${projectId}/episodes/${episodeId}/analysis-settings`, payload),
  saveRedrawAnalysisSettings: (projectId: string, payload: { audio_source: string; source_language: string }) =>
    http.put(`/projects/${projectId}/redraw-analysis-settings`, payload),
  analyze: (projectId: string, episodeId: string) =>
    http.post(`/projects/${projectId}/episodes/${episodeId}/analyze`).then(data<GenerationTask>),
  reanalyze: (projectId: string, episodeId: string) =>
    http.post(`/projects/${projectId}/episodes/${episodeId}/reanalyze`).then(data<GenerationTask>),
  analyzeRedraw: (projectId: string) => http.post(`/projects/${projectId}/redraw-analyze`).then(data<GenerationTask>),
  reanalyzeRedraw: (projectId: string) =>
    http.post(`/projects/${projectId}/redraw-reanalyze`).then(data<GenerationTask>),
  reverseRedrawScript: (projectId: string, episodeId: string) =>
    http.post(`/projects/${projectId}/episodes/${episodeId}/redraw-script`).then(data<GenerationTask>),
  saveRedrawScript: (projectId: string, episodeId: string, content: string) =>
    http.put(`/projects/${projectId}/episodes/${episodeId}/redraw-script`, { content }),
  createAsset: (projectId: string, payload: { asset_type: string; name: string }) =>
    http.post(`/projects/${projectId}/assets`, payload).then(data<ProjectAsset>),
  updateAsset: (projectId: string, assetId: string, payload: Partial<ProjectAsset>) =>
    http.put(`/projects/${projectId}/assets/${assetId}`, payload),
  deleteAsset: (projectId: string, assetId: string) => http.delete(`/projects/${projectId}/assets/${assetId}`),
  uploadAssetImage: (projectId: string, assetId: string, file: File) =>
    upload(`/projects/${projectId}/assets/${assetId}/image`, file),
  removeAssetImage: (projectId: string, assetId: string) =>
    http.delete(`/projects/${projectId}/assets/${assetId}/image`),
  uploadAssetAudio: (projectId: string, assetId: string, file: File, durationMs?: number) =>
    upload(
      `/projects/${projectId}/assets/${assetId}/audio`,
      file,
      durationMs === undefined ? undefined : { duration_ms: String(durationMs) },
    ),
  updateStoryboard: (projectId: string, storyboardId: string, payload: Partial<Storyboard>) =>
    http.put(`/projects/${projectId}/storyboards/${storyboardId}`, payload),
  insertStoryboard: (projectId: string, storyboardId: string, position: "before" | "after") =>
    http.post(`/projects/${projectId}/storyboards/${storyboardId}/insert`, { position }).then(data<Storyboard>),
  deleteStoryboard: (projectId: string, storyboardId: string) =>
    http.delete(`/projects/${projectId}/storyboards/${storyboardId}`),
  reinferStoryboard: (projectId: string, episodeId: string, storyboardId: string) =>
    http
      .post(`/projects/${projectId}/episodes/${episodeId}/storyboards/${storyboardId}/reinfer`)
      .then(data<GenerationTask>),
  reinferRedrawStoryboard: (projectId: string, storyboardId: string) =>
    http.post(`/projects/${projectId}/storyboards/${storyboardId}/redraw-reinfer`).then(data<GenerationTask>),
  generate: (
    projectId: string,
    episodeId: string,
    storyboardId: string,
    taskType: "image_generation" | "video_generation",
    input: Record<string, unknown>,
  ) =>
    http
      .post(`/projects/${projectId}/episodes/${episodeId}/storyboards/${storyboardId}/generate`, {
        task_type: taskType,
        input,
      })
      .then(data<GenerationTask>),
  tasks: (projectId: string, episodeId?: string) =>
    http.get(`/projects/${projectId}/tasks`, { params: { episode_id: episodeId } }).then(data<GenerationTask[]>),
  cancelTask: (projectId: string, taskId: string) => http.post(`/projects/${projectId}/tasks/${taskId}/cancel`),
  outputs: (projectId: string, storyboardId: string) =>
    http.get(`/projects/${projectId}/storyboards/${storyboardId}/outputs`).then(data<GenerationOutput[]>),
  removeStoryboardImage: (projectId: string, storyboardId: string) =>
    http.delete(`/projects/${projectId}/storyboards/${storyboardId}/image`),
  activateOutput: (projectId: string, storyboardId: string, outputId: string) =>
    http.put(`/projects/${projectId}/storyboards/${storyboardId}/outputs/${outputId}/activate`),
  addStoryboardCandidate: (projectId: string, storyboardId: string, outputId: string) =>
    http.put(`/projects/${projectId}/storyboards/${storyboardId}/outputs/${outputId}/candidate`),
  removeStoryboardCandidate: (projectId: string, storyboardId: string, outputId: string) =>
    http.delete(`/projects/${projectId}/storyboards/${storyboardId}/outputs/${outputId}/candidate`),
  deleteOutput: (projectId: string, storyboardId: string, outputId: string) =>
    http.delete(`/projects/${projectId}/storyboards/${storyboardId}/outputs/${outputId}`),
  assetOutputs: (projectId: string, assetId: string) =>
    http.get(`/projects/${projectId}/assets/${assetId}/outputs`).then(data<GenerationOutput[]>),
  activateAssetOutput: (projectId: string, assetId: string, outputId: string) =>
    http.put(`/projects/${projectId}/assets/${assetId}/outputs/${outputId}/activate`),
  deleteAssetOutput: (projectId: string, assetId: string, outputId: string) =>
    http.delete(`/projects/${projectId}/assets/${assetId}/outputs/${outputId}`),
  media: (mediaId: string) =>
    http.get(`/media/${mediaId}`, { responseType: "blob", timeout: 0 }).then((response) => response.data as Blob),
  scriptAnalyses: () => http.get("/script-analyses").then(data<ScriptAnalysis[]>),
  createScriptAnalysis: () => http.post("/script-analyses").then(data<ScriptAnalysis>),
  scriptAnalysisImportProjects: () =>
    http.get("/script-analyses/import-projects").then(data<ScriptAnalysisImportProject[]>),
  scriptAnalysis: (id: string) => http.get(`/script-analyses/${id}`).then(data<ScriptAnalysis>),
  updateScriptAnalysis: (id: string, payload: { name: string; source_content: string; result_content: string }) =>
    http.put(`/script-analyses/${id}`, payload).then(data<ScriptAnalysis>),
  deleteScriptAnalysis: (id: string) => http.delete(`/script-analyses/${id}`),
  importScriptAnalysisProject: (id: string, projectId: string) =>
    http.post(`/script-analyses/${id}/import-project`, { project_id: projectId }).then(data<ScriptAnalysis>),
  importScriptAnalysisFile: (id: string, file: File) =>
    upload<ScriptAnalysis>(`/script-analyses/${id}/import-file`, file),
  analyzeScriptAnalysis: (id: string) => http.post(`/script-analyses/${id}/analyze`).then(data<GenerationTask>),
  cancelScriptAnalysis: (id: string) => http.post(`/script-analyses/${id}/cancel`),
  userModelConfigs: (scope: "script_analysis") => http.get(`/user/model-configs/${scope}`).then(data<ModelConfig[]>),
  saveUserModelConfig: (scope: "script_analysis", modelType: "text", modelId: string) =>
    http.put(`/user/model-configs/${scope}/${modelType}`, { model_id: modelId }),
};

function upload<T = Record<string, unknown>>(path: string, file: File, fields?: Record<string, string>) {
  const form = new FormData();
  form.append("file", file);
  Object.entries(fields || {}).forEach(([key, value]) => form.append(key, value));
  return http.post(path, form, { timeout: 0, headers: { "Content-Type": "multipart/form-data" } }).then(data<T>);
}
