import { isChinaWorkday } from './china-workday-calendar';
import { formatLocalDate } from './format';

export type VersionDevelopmentType = 'agile' | 'standard' | 'waterfall' | 'hotfix';

export interface VersionDevelopmentStageEstimate {
  key: 'product_design' | 'development' | 'testing';
  label: '产品设计' | '开发' | '测试';
  workDays: number;
}

export interface VersionDevelopmentTypeOption {
  key: VersionDevelopmentType;
  label: string;
  description: string;
  stages: VersionDevelopmentStageEstimate[];
  totalWorkDays: number;
}

export interface NewVersionFormState {
  productId: string;
  projectId: string;
  versionNumber: string;
  developmentType: VersionDevelopmentType | '';
  expectedReleaseDate: string;
  submitting: boolean;
}

export interface VersionEditFormState {
  versionNumber: string;
  expectedReleaseDate: string;
  submitting: boolean;
}

export const VERSION_DEVELOPMENT_TYPE_OPTIONS: VersionDevelopmentTypeOption[] = [
  makeDevelopmentTypeOption('agile', '敏捷迭代', '适合常规双周迭代', [
    { key: 'product_design', label: '产品设计', workDays: 2 },
    { key: 'development', label: '开发', workDays: 8 },
    { key: 'testing', label: '测试', workDays: 3 },
  ]),
  makeDevelopmentTypeOption('standard', '常规项目', '适合需求较完整的普通版本', [
    { key: 'product_design', label: '产品设计', workDays: 3 },
    { key: 'development', label: '开发', workDays: 12 },
    { key: 'testing', label: '测试', workDays: 4 },
  ]),
  makeDevelopmentTypeOption('waterfall', '瀑布项目', '适合方案先行的大范围交付', [
    { key: 'product_design', label: '产品设计', workDays: 5 },
    { key: 'development', label: '开发', workDays: 20 },
    { key: 'testing', label: '测试', workDays: 7 },
  ]),
  makeDevelopmentTypeOption('hotfix', '紧急修复', '适合线上缺陷或很小范围改动', [
    { key: 'product_design', label: '产品设计', workDays: 0 },
    { key: 'development', label: '开发', workDays: 2 },
    { key: 'testing', label: '测试', workDays: 1 },
  ]),
];

export function canSubmitNewVersionForm(state: NewVersionFormState): boolean {
  return Boolean(
    state.productId &&
    state.projectId &&
    state.versionNumber &&
    state.developmentType &&
    state.expectedReleaseDate &&
    !state.submitting,
  );
}

export function canSubmitVersionEditForm(state: VersionEditFormState): boolean {
  return Boolean(
    state.versionNumber.trim() &&
    state.expectedReleaseDate &&
    !state.submitting,
  );
}

export function getEditableVersionNumber(projectName: string, versionName: string): string {
  const exactPrefix = `${projectName}V`;
  if (projectName && versionName.toLowerCase().startsWith(exactPrefix.toLowerCase())) {
    return versionName.slice(exactPrefix.length);
  }
  const match = versionName.match(/V([\d.]+)$/i);
  return match?.[1] ?? versionName;
}

export function buildVersionName(projectName: string, versionNumber: string): string {
  return `${projectName}V${versionNumber.trim()}`;
}

export function getVersionDevelopmentTypeOption(type: VersionDevelopmentType): VersionDevelopmentTypeOption | undefined {
  return VERSION_DEVELOPMENT_TYPE_OPTIONS.find((option) => option.key === type);
}

export function getRecommendedExpectedReleaseDate(
  type: VersionDevelopmentType,
  baseDate: Date = new Date(),
  options: { productDesignCompleted?: boolean } = {},
): string {
  const developmentType = getVersionDevelopmentTypeOption(type);
  if (!developmentType) return '';
  const totalWorkDays = getRecommendedWorkDays(developmentType, options);
  return addChinaWorkDays(baseDate, totalWorkDays);
}

export function getRecommendedWorkDays(
  option: VersionDevelopmentTypeOption,
  options: { productDesignCompleted?: boolean } = {},
): number {
  return option.stages.reduce((sum, stage) => {
    if (stage.key === 'product_design' && options.productDesignCompleted) return sum;
    return sum + stage.workDays;
  }, 0);
}

function makeDevelopmentTypeOption(
  key: VersionDevelopmentType,
  label: string,
  description: string,
  stages: VersionDevelopmentStageEstimate[],
): VersionDevelopmentTypeOption {
  return {
    key,
    label,
    description,
    stages,
    totalWorkDays: stages.reduce((sum, stage) => sum + stage.workDays, 0),
  };
}

function addChinaWorkDays(baseDate: Date, workDays: number): string {
  const cursor = new Date(baseDate);
  cursor.setHours(0, 0, 0, 0);
  let remaining = Math.max(1, Math.round(workDays));

  while (remaining > 0) {
    if (isChinaWorkday(cursor)) remaining -= 1;
    if (remaining <= 0) break;
    cursor.setDate(cursor.getDate() + 1);
  }

  return formatLocalDate(cursor);
}
