<script setup lang="ts">
import { useMutation, useQuery } from '@vue/apollo-composable';
import {
  CompleteOrderDocument,
  Decision,
  ManagerFinalizeOrderDocument,
  ManagerSetOrderOfferDocument,
  OrderDetailDocument,
  StartOrderWorkDocument,
  type OrderDetailQuery,
} from '~/composables/graphql/generated';
import {
  formatPrice,
  orderLogisticsStateText,
  orderDeliveryStateText,
} from '~/composables/useOrderDetailPresentation';
import { formatOrderCode } from '~/composables/useOrderCodePresentation';

definePageMeta({
  middleware: ['manager-only'],
});

const route = useRoute();
const orderId = computed(() => String(route.params.id || ''));

type ManagerOrderItem = NonNullable<OrderDetailQuery['order']>;
type StatusAction = 'APPROVE' | 'REJECT' | 'START' | 'COMPLETE';
type StatusActionOption = {
  value: StatusAction;
  label: string;
};

const orderQuery = useQuery(OrderDetailDocument, () => ({
  id: orderId.value,
}));

const completeOrderMutation = useMutation(CompleteOrderDocument);
const finalizeOrderMutation = useMutation(ManagerFinalizeOrderDocument);
const startWorkMutation = useMutation(StartOrderWorkDocument);
const setOfferMutation = useMutation(ManagerSetOrderOfferDocument);

const itemPriceDrafts = reactive<Record<string, string>>({});
const deliveryTermsDraft = ref('');
const deliveryFeeDraft = ref('');
const editingPriceItemId = ref<string | null>(null);
const editingDeliveryTerms = ref(false);
const editingDeliveryFee = ref(false);
const editingStatus = ref(false);
const statusActionDraft = ref<StatusAction | ''>('');
const autosavePending = ref(false);
const statusMutationPending = ref(false);
let autosaveTimer: ReturnType<typeof setTimeout> | null = null;

const currentOrder = computed<ManagerOrderItem | null>(() =>
  orderQuery.result.value?.order ?? null,
);

const currentOrderCode = computed(() => formatOrderCode(currentOrder.value?.code));

watch(
  currentOrder,
  (order) => {
    editingPriceItemId.value = null;
    editingDeliveryTerms.value = false;
    editingDeliveryFee.value = false;
    editingStatus.value = false;
    statusActionDraft.value = '';

    for (const key of Object.keys(itemPriceDrafts)) {
      delete itemPriceDrafts[key];
    }

    if (!order) {
      deliveryTermsDraft.value = '';
      deliveryFeeDraft.value = '';
      return;
    }

    for (const item of order.items) {
      itemPriceDrafts[item.id] = item.unitPrice == null ? '' : String(item.unitPrice);
    }

    deliveryTermsDraft.value = order.deliveryTerms ?? '';
    deliveryFeeDraft.value = order.deliveryFee == null ? '' : String(order.deliveryFee);
  },
  { immediate: true },
);

function parseMoneyDraft(value: string) {
  const trimmed = String(value).replace(',', '.').trim();
  if (!trimmed) {
    return null;
  }

  const normalized = Number(trimmed);
  if (!Number.isFinite(normalized) || normalized < 0) {
    return null;
  }

  return Math.round((normalized + Number.EPSILON) * 100) / 100;
}

const draftDeliveryTerms = computed(() => deliveryTermsDraft.value.trim() || currentOrder.value?.deliveryTerms || null);
const draftDeliveryFee = computed(() => parseMoneyDraft(deliveryFeeDraft.value) ?? currentOrder.value?.deliveryFee ?? null);
const canEditOffer = computed(() => (
  currentOrder.value != null
  && ['NEW', 'MANAGER_PROCESSING', 'WAITING_DOUBLE_CONFIRM', 'CONFIRMED'].includes(currentOrder.value.status)
));
const activePriceItemIds = computed(() => (
  editingPriceItemId.value ? [editingPriceItemId.value] : []
));
const managerStatusSummary = computed(() => {
  if (!currentOrder.value) {
    return '';
  }

  if (['NEW', 'MANAGER_PROCESSING'].includes(currentOrder.value.status)) {
    return 'Заполните цены по позициям и логистике. После этого заказ можно перевести в предложение.';
  }

  if (['WAITING_DOUBLE_CONFIRM', 'CONFIRMED'].includes(currentOrder.value.status)) {
    return 'Предложение уже собрано. Следующий шаг для менеджера: перевести заказ в работу или остановить его.';
  }

  if (currentOrder.value.status === 'IN_PROGRESS') {
    return 'Заказ уже в работе. После исполнения его можно завершить.';
  }

  if (currentOrder.value.status === 'COMPLETED') {
    return 'Заказ завершён и больше не редактируется.';
  }

  return 'Заказ остановлен. Если нужно продолжить работу, сначала поправьте условия и затем снова переведите его в предложение.';
});
const statusActions = computed<StatusActionOption[]>(() => {
  if (!currentOrder.value) {
    return [];
  }

  const options: StatusActionOption[] = [];

  if (offerReady.value && ['NEW', 'MANAGER_PROCESSING', 'MANAGER_BLOCKED', 'CLIENT_REJECTED', 'MANAGER_REJECTED'].includes(currentOrder.value.status)) {
    options.push({ value: 'APPROVE', label: 'Предложение' });
  }

  if (['NEW', 'MANAGER_PROCESSING', 'WAITING_DOUBLE_CONFIRM', 'CONFIRMED', 'MANAGER_BLOCKED'].includes(currentOrder.value.status)) {
    options.push({ value: 'REJECT', label: 'Отклонен' });
  }

  if (['WAITING_DOUBLE_CONFIRM', 'CONFIRMED'].includes(currentOrder.value.status)) {
    options.push({ value: 'START', label: 'В работе' });
  }

  if (currentOrder.value.status === 'IN_PROGRESS') {
    options.push({ value: 'COMPLETE', label: 'Завершен' });
  }

  return options;
});
const canEditStatus = computed(() => statusActions.value.length > 0);

const offerSignature = computed(() => {
  if (!currentOrder.value) {
    return '';
  }

  return JSON.stringify({
    deliveryTerms: deliveryTermsDraft.value.trim(),
    deliveryFee: parseMoneyDraft(deliveryFeeDraft.value),
    itemPrices: currentOrder.value.items.map((item) => ({
      itemId: item.id,
      unitPrice: parseMoneyDraft(itemPriceDrafts[item.id] ?? ''),
    })),
  });
});

const publishedSignature = computed(() => {
  if (!currentOrder.value) {
    return '';
  }

  return JSON.stringify({
    deliveryTerms: currentOrder.value.deliveryTerms ?? '',
    deliveryFee: currentOrder.value.deliveryFee ?? null,
    itemPrices: currentOrder.value.items.map((item) => ({
      itemId: item.id,
      unitPrice: item.unitPrice ?? null,
    })),
  });
});

const offerReady = computed(() => {
  if (!currentOrder.value) {
    return false;
  }

  const deliveryFee = parseMoneyDraft(deliveryFeeDraft.value);
  if (deliveryFee == null) {
    return false;
  }

  return currentOrder.value.items.every((item) => parseMoneyDraft(itemPriceDrafts[item.id] ?? '') != null);
});

const offerTotal = computed(() => {
  if (!currentOrder.value || !offerReady.value) {
    return null;
  }

  const productsTotal = currentOrder.value.items.reduce((sum, item) => (
    sum + item.quantity * (parseMoneyDraft(itemPriceDrafts[item.id] ?? '') ?? 0)
  ), 0);

  return Math.round((productsTotal + (parseMoneyDraft(deliveryFeeDraft.value) ?? 0) + Number.EPSILON) * 100) / 100;
});

async function refetchOrder() {
  await orderQuery.refetch({ id: orderId.value });
}

async function focusElement(selector: string) {
  await nextTick();
  document.querySelector<HTMLInputElement | HTMLSelectElement>(selector)?.focus();
}

async function saveOffer() {
  if (!currentOrder.value || !offerReady.value || !canEditOffer.value) {
    return;
  }

  autosavePending.value = true;
  try {
    await setOfferMutation.mutate({
      input: {
        orderId: currentOrder.value.id,
        itemPrices: currentOrder.value.items.map((item) => ({
          itemId: item.id,
          unitPrice: parseMoneyDraft(itemPriceDrafts[item.id] ?? '') ?? 0,
        })),
        deliveryTerms: deliveryTermsDraft.value.trim(),
        deliveryFee: parseMoneyDraft(deliveryFeeDraft.value) ?? 0,
      },
    });
    await refetchOrder();
  }
  finally {
    autosavePending.value = false;
  }
}

async function openPriceEditor(itemId: string) {
  if (!canEditOffer.value) {
    return;
  }

  editingPriceItemId.value = itemId;
  await focusElement(`[data-unit-price-input="${itemId}"]`);
}

function closePriceEditor(itemId: string) {
  if (editingPriceItemId.value === itemId) {
    editingPriceItemId.value = null;
  }
}

async function openDeliveryTermsEditor() {
  if (!canEditOffer.value) {
    return;
  }

  editingDeliveryTerms.value = true;
  await focusElement('[data-delivery-terms-input]');
}

function closeDeliveryTermsEditor() {
  editingDeliveryTerms.value = false;
}

async function openDeliveryFeeEditor() {
  if (!canEditOffer.value) {
    return;
  }

  editingDeliveryFee.value = true;
  await focusElement('[data-delivery-fee-input]');
}

function closeDeliveryFeeEditor() {
  editingDeliveryFee.value = false;
}

async function openStatusEditor() {
  if (!canEditStatus.value || statusMutationPending.value) {
    return;
  }

  editingStatus.value = true;
  statusActionDraft.value = '';
  await focusElement('[data-manager-status-select]');
}

function closeStatusEditor() {
  if (!statusMutationPending.value) {
    editingStatus.value = false;
    statusActionDraft.value = '';
  }
}

async function applyStatusAction() {
  if (!currentOrder.value || !statusActionDraft.value) {
    closeStatusEditor();
    return;
  }

  statusMutationPending.value = true;

  try {
    if (statusActionDraft.value === 'APPROVE') {
      await finalizeOrderMutation.mutate({
        orderId: currentOrder.value.id,
        decision: Decision.Approve,
      });
    }
    else if (statusActionDraft.value === 'REJECT') {
      await finalizeOrderMutation.mutate({
        orderId: currentOrder.value.id,
        decision: Decision.Reject,
      });
    }
    else if (statusActionDraft.value === 'START') {
      await startWorkMutation.mutate({ orderId: currentOrder.value.id });
    }
    else if (statusActionDraft.value === 'COMPLETE') {
      await completeOrderMutation.mutate({ orderId: currentOrder.value.id });
    }

    await refetchOrder();
  }
  finally {
    statusMutationPending.value = false;
    closeStatusEditor();
  }
}

watch(
  [offerReady, offerSignature, publishedSignature],
  ([ready, nextSignature, currentSignature]) => {
    if (autosaveTimer) {
      clearTimeout(autosaveTimer);
      autosaveTimer = null;
    }

    if (!ready || !canEditOffer.value || !nextSignature || nextSignature === currentSignature || autosavePending.value) {
      return;
    }

    autosaveTimer = setTimeout(() => {
      void saveOffer();
    }, 700);
  },
);
</script>

<template>
  <section class="space-y-6">
    <NuxtLink to="/client-orders" class="text-sm font-semibold text-[#0d854a]">← Назад к заказам клиентов</NuxtLink>

    <div v-if="orderQuery.loading.value" class="manager-empty-state">
      Загружаем заказ...
    </div>

    <div v-else-if="!currentOrder" class="manager-empty-state">
      Заказ не найден.
    </div>

    <template v-else>
      <div class="manager-hero">
        <p class="manager-eyebrow">Заказ</p>
        <h1 class="manager-title">{{ currentOrderCode }}</h1>
      </div>

      <div class="space-y-4">
        <div class="surface-card rounded-3xl p-5">
          <div class="flex flex-wrap items-start justify-between gap-4">
            <div class="space-y-2">
              <p class="text-[11px] font-semibold uppercase tracking-[0.18em] text-[#6a8a76]">Статус заказа</p>

              <label v-if="editingStatus && canEditStatus" class="block">
                <select
                  v-model="statusActionDraft"
                  data-manager-status-select
                  class="w-full min-w-[220px] rounded-2xl bg-[#f3f5f4] px-4 py-3 text-sm font-semibold text-[#123824] outline-none transition focus:shadow-[0_0_0_3px_rgba(19,153,87,0.12)]"
                  :disabled="statusMutationPending"
                  @change="void applyStatusAction()"
                  @blur="closeStatusEditor"
                >
                  <option value="" disabled>Выберите статус</option>
                  <option
                    v-for="option in statusActions"
                    :key="option.value"
                    :value="option.value"
                  >
                    {{ option.label }}
                  </option>
                </select>
              </label>

              <button
                v-else
                type="button"
                class="rounded-2xl px-0 py-0 text-left"
                :class="canEditStatus ? 'cursor-pointer' : 'cursor-default'"
                @dblclick="void openStatusEditor()"
              >
                <OrdersOrderStatusBadge :status="currentOrder.status" />
              </button>
            </div>

            <p class="text-sm text-[#5c7b69]">
              {{
                statusMutationPending
                  ? 'Обновляем статус...'
                  : canEditStatus
                    ? 'Двойной клик по статусу, чтобы изменить.'
                    : 'Статус уже финальный.'
              }}
            </p>
          </div>

          <p class="mt-4 max-w-2xl text-sm leading-6 text-[#355947]">
            {{ managerStatusSummary }}
          </p>
        </div>

        <div>
          <h2 class="text-xl font-bold text-[#123824]">Состав заказа</h2>
          <OrdersOrderItemsTable
            class="mt-4"
            :items="currentOrder.items"
            :calculation-payload="currentOrder.calculationPayload"
            mode="manager-pricing"
            :unit-price-drafts="itemPriceDrafts"
            :editable-price-item-ids="activePriceItemIds"
            :disabled="!canEditOffer"
            :framed="false"
            price-placeholder="Рассчитывается"
            @update:unit-price="({ itemId, value }) => { itemPriceDrafts[itemId] = value; }"
            @activate:unit-price="void openPriceEditor($event)"
            @finish:unit-price="closePriceEditor($event)"
          />
        </div>

        <div class="surface-card rounded-3xl p-5">
          <h2 class="text-xl font-bold text-[#123824]">Доставка</h2>
          <div class="mt-4 space-y-4 text-sm text-[#123824]">
            <div class="space-y-1">
              <p class="text-[11px] font-semibold uppercase tracking-[0.18em] text-[#6a8a76]">Адрес</p>
              <p class="text-base font-semibold">{{ currentOrder.deliveryAddress || 'Адрес пока не указан' }}</p>
            </div>
            <div class="grid gap-4 md:grid-cols-2">
              <div class="space-y-3">
                <p class="text-[11px] font-semibold uppercase tracking-[0.18em] text-[#6a8a76]">Комментарий по доставке</p>
                <label v-if="editingDeliveryTerms" class="form-control">
                  <input
                    v-model="deliveryTermsDraft"
                    data-delivery-terms-input
                    type="text"
                    placeholder="Например, доставка до склада 2-3 дня"
                    class="input input-bordered manager-field w-full rounded-2xl bg-white"
                    :disabled="!canEditOffer"
                    @blur="closeDeliveryTermsEditor"
                    @keydown.enter="closeDeliveryTermsEditor"
                  >
                </label>
                <button
                  v-else
                  type="button"
                  class="w-full rounded-2xl px-0 py-0 text-left text-sm text-[#123824]"
                  :class="canEditOffer ? 'cursor-pointer transition hover:text-[#0d854a]' : 'cursor-default'"
                  @dblclick="void openDeliveryTermsEditor()"
                >
                  {{ orderDeliveryStateText(draftDeliveryTerms) }}
                </button>
              </div>
              <div class="space-y-3">
                <p class="text-[11px] font-semibold uppercase tracking-[0.18em] text-[#6a8a76]">Стоимость логистики</p>
                <label v-if="editingDeliveryFee" class="form-control">
                  <input
                    v-model="deliveryFeeDraft"
                    data-delivery-fee-input
                    type="number"
                    min="0"
                    step="0.01"
                    placeholder="Например, 3000"
                    class="input input-bordered manager-field w-full rounded-2xl bg-white"
                    :disabled="!canEditOffer"
                    @blur="closeDeliveryFeeEditor"
                    @keydown.enter="closeDeliveryFeeEditor"
                  >
                </label>
                <button
                  v-else
                  type="button"
                  class="w-full rounded-2xl px-0 py-0 text-left text-sm text-[#123824]"
                  :class="canEditOffer ? 'cursor-pointer transition hover:text-[#0d854a]' : 'cursor-default'"
                  @dblclick="void openDeliveryFeeEditor()"
                >
                  {{ orderLogisticsStateText(draftDeliveryFee) }}
                </button>
              </div>
            </div>
          </div>

          <div class="mt-4 flex flex-wrap items-center justify-between gap-3">
            <p class="text-sm text-[#5c7b69]">
              {{
                offerTotal == null
                  ? 'Итог по заказу появится после заполнения всех цен.'
                  : autosavePending
                    ? `Сохраняем: ${formatPrice(offerTotal)}`
                    : `Текущий итог: ${formatPrice(offerTotal)}`
              }}
            </p>

            <p v-if="canEditOffer" class="text-xs font-semibold uppercase tracking-[0.14em] text-[#6a8a76]">
              Двойной клик по цене или условиям, чтобы изменить.
            </p>
          </div>
        </div>
      </div>
    </template>
  </section>
</template>
