type OrderStatusCode =
  | 'NEW'
  | 'MANAGER_PROCESSING'
  | 'WAITING_DOUBLE_CONFIRM'
  | 'CLIENT_REJECTED'
  | 'MANAGER_REJECTED'
  | 'MANAGER_BLOCKED'
  | 'CONFIRMED'
  | 'IN_PROGRESS'
  | 'COMPLETED';

export type OrderStatusTone = 'warning' | 'info' | 'success' | 'danger';

type TimelineStage = {
  code: string;
  label: string;
  note: string;
  dateLabel: string;
  state: 'done' | 'current' | 'upcoming';
};

type StatusBadgePresentation = {
  label: string;
  tone: OrderStatusTone;
};

type StatusPresentation = {
  title: string;
  summary: string;
  stages: TimelineStage[];
};

const STAGE_ORDER: OrderStatusCode[] = [
  'NEW',
  'MANAGER_PROCESSING',
  'WAITING_DOUBLE_CONFIRM',
  'CONFIRMED',
  'IN_PROGRESS',
  'COMPLETED',
];

const DAY_FORMATTER = new Intl.DateTimeFormat('ru-RU', {
  day: 'numeric',
  month: 'long',
});

const STATUS_BADGE_MAP: Record<string, StatusBadgePresentation> = {
  NEW: { label: 'Заявка', tone: 'warning' },
  MANAGER_PROCESSING: { label: 'Готовим предложение', tone: 'warning' },
  WAITING_DOUBLE_CONFIRM: { label: 'Предложение', tone: 'info' },
  CLIENT_REJECTED: { label: 'Отклонен', tone: 'danger' },
  MANAGER_REJECTED: { label: 'Отклонен', tone: 'danger' },
  MANAGER_BLOCKED: { label: 'Пауза', tone: 'warning' },
  CONFIRMED: { label: 'Производство', tone: 'info' },
  IN_PROGRESS: { label: 'Отгрузка', tone: 'success' },
  COMPLETED: { label: 'Доставка', tone: 'success' },
};

function addDays(date: Date, days: number) {
  const next = new Date(date);
  next.setDate(next.getDate() + days);
  return next;
}

function formatDay(date: Date) {
  return DAY_FORMATTER.format(date);
}

function stageIndex(status: string) {
  const index = STAGE_ORDER.indexOf(status as OrderStatusCode);
  return index >= 0 ? index : 0;
}

function buildDates(createdAt: string | Date) {
  const base = new Date(createdAt);

  return {
    created: base,
    offer: addDays(base, 1),
    approval: addDays(base, 2),
    production: addDays(base, 4),
    shipment: addDays(base, 6),
    delivered: addDays(base, 8),
  };
}

function buildManagerStages(status: string, createdAt: string | Date): StatusPresentation {
  const dates = buildDates(createdAt);

  const isOfferStage = ['WAITING_DOUBLE_CONFIRM', 'CONFIRMED'].includes(status);
  const isWorkStage = ['IN_PROGRESS', 'COMPLETED'].includes(status);
  const isStopped = ['CLIENT_REJECTED', 'MANAGER_REJECTED', 'MANAGER_BLOCKED'].includes(status);

  const stages: TimelineStage[] = [
    {
      code: 'NEW',
      label: 'Заявка',
      note: 'Заказ создан и ждёт расчёта.',
      dateLabel: formatDay(dates.created),
      state: isOfferStage || isWorkStage || isStopped ? 'done' : 'current',
    },
    {
      code: 'WAITING_DOUBLE_CONFIRM',
      label: 'Предложение',
      note: 'Цена и условия опубликованы клиенту.',
      dateLabel: formatDay(dates.offer),
      state: isWorkStage ? 'done' : isOfferStage ? 'current' : 'upcoming',
    },
    {
      code: 'IN_PROGRESS',
      label: status === 'COMPLETED' ? 'Исполнение завершено' : 'В работе',
      note: status === 'COMPLETED'
        ? 'Заказ передан в работу и закрыт.'
        : 'Заказ передан в производство или исполнение.',
      dateLabel: formatDay(dates.production),
      state: isWorkStage ? 'current' : 'upcoming',
    },
  ];

  if (status === 'MANAGER_BLOCKED') {
    return {
      title: 'Заказ на паузе',
      summary: 'Нужно уточнение по заказу перед публикацией предложения.',
      stages,
    };
  }

  if (status === 'CLIENT_REJECTED' || status === 'MANAGER_REJECTED') {
    return {
      title: 'Заказ остановлен',
      summary: 'Текущий заказ завершён без запуска в работу.',
      stages,
    };
  }

  if (isWorkStage) {
    return {
      title: status === 'COMPLETED' ? 'Заказ завершён' : 'Заказ в работе',
      summary: status === 'COMPLETED'
        ? 'Исполнение завершено, история этапов сохранена.'
        : 'Предложение согласовано, заказ уже в работе.',
      stages,
    };
  }

  if (isOfferStage) {
    return {
      title: 'Предложение отправлено',
      summary: 'Клиент уже видит цену и условия. Следующий шаг для менеджера: пустить заказ в работу.',
      stages,
    };
  }

  return {
    title: 'Ждём расчёт по заявке',
    summary: 'Заполните цену по позициям и логистике, после этого предложение уйдёт клиенту автоматически.',
    stages,
  };
}

function buildClientStages(status: string, createdAt: string | Date): StatusPresentation {
  const dates = buildDates(createdAt);

  if (status === 'CLIENT_REJECTED' || status === 'MANAGER_REJECTED') {
    return {
      title: 'Заказ остановлен',
      summary: 'Текущий заказ закрыт. При необходимости можно оформить новый заказ.',
      stages: [
        {
          code: 'NEW',
          label: 'Заявка',
          note: 'Заказ принят в обработку.',
          dateLabel: formatDay(dates.created),
          state: 'done',
        },
        {
          code: status,
          label: 'Отклонен',
          note: 'Дальнейшее исполнение не планируется.',
          dateLabel: formatDay(dates.approval),
          state: 'current',
        },
      ],
    };
  }

  if (status === 'MANAGER_BLOCKED') {
    return {
      title: 'Заказ ждёт уточнения',
      summary: 'Менеджер уточняет параметры заказа перед расчётом.',
      stages: [
        {
          code: 'NEW',
          label: 'Заявка',
          note: 'Заказ принят в обработку.',
          dateLabel: formatDay(dates.created),
          state: 'done',
        },
        {
          code: status,
          label: 'Пауза',
          note: 'После уточнения покажем плановые даты по исполнению.',
          dateLabel: formatDay(dates.approval),
          state: 'current',
        },
      ],
    };
  }

  const currentIndex = stageIndex(status);

  const stages: TimelineStage[] = [
    {
      code: 'NEW',
      label: 'Заявка',
      note: 'Приняли заказ и начали обработку.',
      dateLabel: formatDay(dates.created),
      state: currentIndex > 0 ? 'done' : currentIndex === 0 ? 'current' : 'upcoming',
    },
    {
      code: 'MANAGER_PROCESSING',
      label: 'Готовим предложение',
      note: 'Собираем стоимость и плановые сроки по заказу.',
      dateLabel: formatDay(dates.offer),
      state: currentIndex > 1 ? 'done' : currentIndex === 1 ? 'current' : 'upcoming',
    },
    {
      code: 'WAITING_DOUBLE_CONFIRM',
      label: 'Предложение',
      note: 'Цена и условия готовы, ждём подтверждения.',
      dateLabel: formatDay(dates.approval),
      state: currentIndex > 2 ? 'done' : currentIndex === 2 ? 'current' : 'upcoming',
    },
    {
      code: 'CONFIRMED',
      label: 'Производство',
      note: 'Плановая дата запуска или выхода из производства.',
      dateLabel: formatDay(dates.production),
      state: currentIndex > 3 ? 'done' : currentIndex === 3 ? 'current' : 'upcoming',
    },
    {
      code: 'IN_PROGRESS',
      label: 'Отгрузка',
      note: 'Плановая дата передачи в логистику.',
      dateLabel: formatDay(dates.shipment),
      state: currentIndex > 4 ? 'done' : currentIndex === 4 ? 'current' : 'upcoming',
    },
    {
      code: 'COMPLETED',
      label: 'Доставка',
      note: 'Плановая дата получения заказа.',
      dateLabel: formatDay(dates.delivered),
      state: currentIndex === 5 ? 'current' : 'upcoming',
    },
  ];

  if (status === 'NEW') {
    return {
      title: 'Заказ создан',
      summary: 'Менеджер рассчитывает стоимость и готовит план по исполнению.',
      stages,
    };
  }

  if (status === 'MANAGER_PROCESSING') {
    return {
      title: 'Готовим предложение',
      summary: 'Собираем итоговые условия и скоро покажем плановые даты.',
      stages,
    };
  }

  if (status === 'WAITING_DOUBLE_CONFIRM') {
    return {
      title: 'Предложение готово',
      summary: 'Стоимость и условия уже рассчитаны. Следующий этап после запуска: производство.',
      stages,
    };
  }

  if (status === 'CONFIRMED') {
    return {
      title: 'Производство запланировано',
      summary: `Ориентируемся на производство ${formatDay(dates.production)}, затем отгрузку и доставку по плану.`,
      stages,
    };
  }

  if (status === 'IN_PROGRESS') {
    return {
      title: 'Готовим отгрузку',
      summary: `Производство идёт. Следующая плановая дата: отгрузка около ${formatDay(dates.shipment)}.`,
      stages,
    };
  }

  return {
    title: 'Доставка по плану',
    summary: `Финальный ориентир по заказу: доставка ${formatDay(dates.delivered)}.`,
    stages,
  };
}

export function getOrderStatusBadgePresentation(status: string): StatusBadgePresentation {
  return STATUS_BADGE_MAP[status] ?? {
    label: status,
    tone: 'info',
  };
}

export function getOrderStatusPresentation(
  status: string,
  createdAt: string | Date,
  audience: 'client' | 'manager' = 'client',
): StatusPresentation {
  return audience === 'manager'
    ? buildManagerStages(status, createdAt)
    : buildClientStages(status, createdAt);
}
