import {
  BackendSongifyVideo,
  SongifyProject,
  SongifyProjectStatus,
  SongifyVideo,
} from '@/types/songify';

// from backend schema to frontend schema
/**
 * Group backend videos by request_id and convert to frontend projects.
 * Multiple videos with same request_id = one project with multiple videos.
 */
export function groupBackendVideosToProjects(
  backendVideos: BackendSongifyVideo[]
): SongifyProject[] {
  // Group by request_id
  const grouped = backendVideos.reduce(
    (acc, video) => {
      if (!acc[video.request_id]) {
        acc[video.request_id] = [];
      }
      acc[video.request_id].push(video);
      return acc;
    },
    {} as Record<string, BackendSongifyVideo[]>
  );

  // Convert each group to a project
  return Object.entries(grouped).map(([requestId, videos]) => {
    const firstVideo = videos[0];
    const projectStatus = determineProjectStatus(videos);

    return {
      requestId: requestId, // Use request_id as project ID
      name: firstVideo.title,
      videos: videos.map((v) => ({
        id: v.final_video_s3_id || v.id.toString(),
        url: v.final_video_s3_id
          ? `https://cdn1.suno.ai/${v.final_video_s3_id}`
          : '',
        status: mapVideoStatus(v.final_status),
        genre: v.genre,
      })),
      createdAt: firstVideo.created_at,
      s3FileName: firstVideo.original_video_s3_id,
      genre: firstVideo.genre,
      numGenerations: videos.length,
      status: projectStatus,
      statusDetails: {
        status: projectStatus,
        terminal: isTerminalStatus(projectStatus),
        occurred_at: firstVideo.updated_at,
        updated_at: firstVideo.updated_at,
      },
    };
  });
}

function determineProjectStatus(
  videos: BackendSongifyVideo[]
): SongifyProjectStatus {
  const statuses = videos.map((v) => v.final_status);

  // Priority: error > failed > generating > completed > pending
  if (statuses.some((s) => s === 'error' || s === 'failed_system')) {
    return SongifyProjectStatus.FAILED_SYSTEM;
  }
  if (statuses.some((s) => s === 'failed_expected')) {
    return SongifyProjectStatus.FAILED_EXPECTED;
  }
  if (statuses.every((s) => s === 'completed')) {
    return SongifyProjectStatus.COMPLETED;
  }
  return SongifyProjectStatus.PENDING;
}

function mapVideoStatus(backendStatus: string): SongifyVideo['status'] {
  if (backendStatus === 'completed') return 'completed';
  if (backendStatus.includes('failed') || backendStatus === 'error')
    return 'failed';
  return 'loading';
}

function isTerminalStatus(status: SongifyProjectStatus): boolean {
  return [
    SongifyProjectStatus.COMPLETED,
    SongifyProjectStatus.FAILED_EXPECTED,
    SongifyProjectStatus.FAILED_SYSTEM,
    SongifyProjectStatus.CANCELLED,
  ].includes(status);
}

// from frontend schema to text
export const getStatusText = (status: SongifyProjectStatus) => {
  switch (status) {
    case SongifyProjectStatus.PENDING:
      return 'Pending';
    case SongifyProjectStatus.PROCESSING_UPLOAD:
      return 'Processing...';
    case SongifyProjectStatus.GENERATING_REMIXES:
      return 'Generating remixes...';
    case SongifyProjectStatus.GENERATING_VIDEOS:
      return 'Creating videos...';
    case SongifyProjectStatus.COMPLETED:
      return 'Completed';
    case SongifyProjectStatus.FAILED_EXPECTED:
    case SongifyProjectStatus.FAILED_SYSTEM:
      return 'Request failed';
    case SongifyProjectStatus.CANCELLED:
      return 'Cancelled';
    case SongifyProjectStatus.ERROR:
      return 'Error';
    default:
      return status;
  }
};
