<script setup lang="ts">
import {
  DeleteOutlined,
  EditOutlined,
  PlusOutlined,
} from "@ant-design/icons-vue";
import { useMutation, useQuery, useQueryClient } from "@tanstack/vue-query";
import { message } from "ant-design-vue";
import type { Brand, BrandLibrarySummary, Competitor, Keyword, Question } from "@geo/shared-types";
import type { TableColumnsType } from "ant-design-vue";
import { computed, reactive, ref, watch } from "vue";
import { useI18n } from "vue-i18n";

import { brandsApi } from "@/lib/api";
import { formatDateTime } from "@/lib/display";
import { formatError } from "@/lib/errors";

const queryClient = useQueryClient();
const { t } = useI18n();

const activeTab = ref("keywords");
const selectedBrandId = ref<number | null>(null);
const selectedKeywordId = ref<number | null>(null);

const brandModalOpen = ref(false);
const editingBrandId = ref<number | null>(null);
const keywordModalOpen = ref(false);
const editingKeywordId = ref<number | null>(null);
const questionModalOpen = ref(false);
const editingQuestionId = ref<number | null>(null);
const competitorModalOpen = ref(false);
const editingCompetitorId = ref<number | null>(null);

const brandForm = reactive({
  name: "",
  website: "",
  description: "",
});

const keywordForm = reactive({
  name: "",
});

const questionForm = reactive({
  keyword_id: undefined as number | undefined,
  question_text: "",
});

const competitorForm = reactive({
  name: "",
  website: "",
  description: "",
  product_lines: "",
});

const brandListQuery = useQuery({
  queryKey: ["brands", "list"],
  queryFn: () => brandsApi.list(),
});

const brandLibrarySummaryQuery = useQuery({
  queryKey: ["brands", "library-summary"],
  queryFn: () => brandsApi.getLibrarySummary(),
});

const keywordsQuery = useQuery({
  queryKey: computed(() => ["brands", selectedBrandId.value, "keywords"]),
  enabled: computed(() => Boolean(selectedBrandId.value)),
  queryFn: () => brandsApi.listKeywords(selectedBrandId.value as number),
});

const allQuestionsQuery = useQuery({
  queryKey: computed(() => ["brands", selectedBrandId.value, "questions", "all"]),
  enabled: computed(() => Boolean(selectedBrandId.value)),
  queryFn: () => brandsApi.listQuestions(selectedBrandId.value as number),
});

const filteredQuestionsQuery = useQuery({
  queryKey: computed(() => ["brands", selectedBrandId.value, "questions", selectedKeywordId.value]),
  enabled: computed(() => Boolean(selectedBrandId.value)),
  queryFn: () => brandsApi.listQuestions(selectedBrandId.value as number, selectedKeywordId.value),
});

const competitorsQuery = useQuery({
  queryKey: computed(() => ["brands", selectedBrandId.value, "competitors"]),
  enabled: computed(() => Boolean(selectedBrandId.value)),
  queryFn: () => brandsApi.listCompetitors(selectedBrandId.value as number),
});

const brandLibrarySummary = computed<BrandLibrarySummary | null>(() => brandLibrarySummaryQuery.data.value ?? null);

const selectedBrand = computed(() =>
  brandListQuery.data.value?.find((item) => item.id === selectedBrandId.value) ?? null,
);

const questionCountByKeyword = computed(() => {
  const counts = new Map<number, number>();
  for (const item of allQuestionsQuery.data.value ?? []) {
    counts.set(item.keyword_id, (counts.get(item.keyword_id) ?? 0) + 1);
  }
  return counts;
});

const selectedBrandKeywordCount = computed(() => selectedBrand.value?.keyword_count ?? 0);
const selectedKeywordQuestionCount = computed(() => {
  if (!selectedKeywordId.value) {
    return 0;
  }
  return questionCountByKeyword.value.get(selectedKeywordId.value) ?? 0;
});

const brandLimitReached = computed(() => {
  if (!brandLibrarySummary.value) {
    return false;
  }
  return brandLibrarySummary.value.remaining_brands <= 0;
});

const keywordLimitReached = computed(() => {
  if (!brandLibrarySummary.value) {
    return false;
  }
  return brandLibrarySummary.value.remaining_keywords <= 0;
});

const questionLimitReached = computed(() => {
  if (!brandLibrarySummary.value || !selectedKeywordId.value) {
    return false;
  }
  return selectedKeywordQuestionCount.value >= brandLibrarySummary.value.max_questions_per_keyword;
});

const brandMutations = {
  create: useMutation({
    mutationFn: () =>
      brandsApi.create({
        name: brandForm.name.trim(),
        website: brandForm.website.trim() || null,
        description: brandForm.description.trim() || null,
      }),
    onSuccess: async (brand) => {
      message.success(t("brands.messages.createBrand"));
      brandModalOpen.value = false;
      selectedBrandId.value = brand.id;
      await Promise.all([
        queryClient.invalidateQueries({ queryKey: ["brands"] }),
        queryClient.invalidateQueries({ queryKey: ["workspace"] }),
      ]);
    },
    onError: (error) => message.error(formatError(error)),
  }),
  update: useMutation({
    mutationFn: () =>
      brandsApi.update(editingBrandId.value as number, {
        name: brandForm.name.trim(),
        website: brandForm.website.trim() || null,
        description: brandForm.description.trim() || null,
      }),
    onSuccess: async () => {
      message.success(t("brands.messages.updateBrand"));
      brandModalOpen.value = false;
      await Promise.all([
        queryClient.invalidateQueries({ queryKey: ["brands"] }),
        queryClient.invalidateQueries({ queryKey: ["workspace"] }),
      ]);
    },
    onError: (error) => message.error(formatError(error)),
  }),
  remove: useMutation({
    mutationFn: (brandId: number) => brandsApi.remove(brandId),
    onSuccess: async () => {
      message.success(t("brands.messages.deleteBrand"));
      selectedBrandId.value = null;
      await Promise.all([
        queryClient.invalidateQueries({ queryKey: ["brands"] }),
        queryClient.invalidateQueries({ queryKey: ["workspace"] }),
      ]);
    },
    onError: (error) => message.error(formatError(error)),
  }),
};

const keywordMutations = {
  create: useMutation({
    mutationFn: () =>
      brandsApi.createKeyword(selectedBrandId.value as number, {
        name: keywordForm.name.trim(),
      }),
    onSuccess: async () => {
      message.success(t("brands.messages.createKeyword"));
      keywordModalOpen.value = false;
      await Promise.all([
        queryClient.invalidateQueries({ queryKey: ["brands"] }),
        queryClient.invalidateQueries({ queryKey: ["brands", selectedBrandId.value, "keywords"] }),
      ]);
    },
    onError: (error) => message.error(formatError(error)),
  }),
  update: useMutation({
    mutationFn: () =>
      brandsApi.updateKeyword(selectedBrandId.value as number, editingKeywordId.value as number, {
        name: keywordForm.name.trim(),
      }),
    onSuccess: async () => {
      message.success(t("brands.messages.updateKeyword"));
      keywordModalOpen.value = false;
      await Promise.all([
        queryClient.invalidateQueries({ queryKey: ["brands"] }),
        queryClient.invalidateQueries({ queryKey: ["brands", selectedBrandId.value, "keywords"] }),
      ]);
    },
    onError: (error) => message.error(formatError(error)),
  }),
  remove: useMutation({
    mutationFn: (keywordId: number) =>
      brandsApi.removeKeyword(selectedBrandId.value as number, keywordId),
    onSuccess: async () => {
      message.success(t("brands.messages.deleteKeyword"));
      if (selectedKeywordId.value === editingKeywordId.value) {
        selectedKeywordId.value = null;
      }
      await Promise.all([
        queryClient.invalidateQueries({ queryKey: ["brands"] }),
        queryClient.invalidateQueries({ queryKey: ["brands", selectedBrandId.value, "keywords"] }),
        queryClient.invalidateQueries({ queryKey: ["brands", selectedBrandId.value, "questions"] }),
      ]);
    },
    onError: (error) => message.error(formatError(error)),
  }),
};

const questionMutations = {
  create: useMutation({
    mutationFn: () =>
      brandsApi.createQuestion(selectedBrandId.value as number, {
        keyword_id: questionForm.keyword_id as number,
        question_text: questionForm.question_text.trim(),
      }),
    onSuccess: async () => {
      message.success(t("brands.messages.createQuestion"));
      questionModalOpen.value = false;
      await Promise.all([
        queryClient.invalidateQueries({ queryKey: ["brands"] }),
        queryClient.invalidateQueries({ queryKey: ["brands", selectedBrandId.value, "questions"] }),
      ]);
    },
    onError: (error) => message.error(formatError(error)),
  }),
  update: useMutation({
    mutationFn: () =>
      brandsApi.updateQuestion(selectedBrandId.value as number, editingQuestionId.value as number, {
        question_text: questionForm.question_text.trim(),
      }),
    onSuccess: async () => {
      message.success(t("brands.messages.updateQuestion"));
      questionModalOpen.value = false;
      await queryClient.invalidateQueries({ queryKey: ["brands", selectedBrandId.value, "questions"] });
    },
    onError: (error) => message.error(formatError(error)),
  }),
  remove: useMutation({
    mutationFn: (questionId: number) =>
      brandsApi.removeQuestion(selectedBrandId.value as number, questionId),
    onSuccess: async () => {
      message.success(t("brands.messages.deleteQuestion"));
      await Promise.all([
        queryClient.invalidateQueries({ queryKey: ["brands"] }),
        queryClient.invalidateQueries({ queryKey: ["brands", selectedBrandId.value, "questions"] }),
      ]);
    },
    onError: (error) => message.error(formatError(error)),
  }),
};

const competitorMutations = {
  create: useMutation({
    mutationFn: () =>
      brandsApi.createCompetitor(selectedBrandId.value as number, {
        name: competitorForm.name.trim(),
        website: competitorForm.website.trim() || null,
        description: competitorForm.description.trim() || null,
        product_lines_json: parseProductLines(competitorForm.product_lines),
      }),
    onSuccess: async () => {
      message.success(t("brands.messages.createCompetitor"));
      competitorModalOpen.value = false;
      await queryClient.invalidateQueries({ queryKey: ["brands", selectedBrandId.value, "competitors"] });
    },
    onError: (error) => message.error(formatError(error)),
  }),
  update: useMutation({
    mutationFn: () =>
      brandsApi.updateCompetitor(selectedBrandId.value as number, editingCompetitorId.value as number, {
        name: competitorForm.name.trim(),
        website: competitorForm.website.trim() || null,
        description: competitorForm.description.trim() || null,
        product_lines_json: parseProductLines(competitorForm.product_lines),
      }),
    onSuccess: async () => {
      message.success(t("brands.messages.updateCompetitor"));
      competitorModalOpen.value = false;
      await queryClient.invalidateQueries({ queryKey: ["brands", selectedBrandId.value, "competitors"] });
    },
    onError: (error) => message.error(formatError(error)),
  }),
  remove: useMutation({
    mutationFn: (competitorId: number) =>
      brandsApi.removeCompetitor(selectedBrandId.value as number, competitorId),
    onSuccess: async () => {
      message.success(t("brands.messages.deleteCompetitor"));
      await queryClient.invalidateQueries({ queryKey: ["brands", selectedBrandId.value, "competitors"] });
    },
    onError: (error) => message.error(formatError(error)),
  }),
};

const selectedKeyword = computed(() =>
  keywordsQuery.data.value?.find((item) => item.id === selectedKeywordId.value) ?? null,
);

const questionColumns = computed<TableColumnsType<Question>>(() => [
  {
    title: t("brands.sections.questions"),
    dataIndex: "question_text",
    key: "question_text",
  },
  {
    title: t("common.createdAt"),
    dataIndex: "created_at",
    key: "created_at",
    width: 180,
  },
  {
    title: t("common.actions"),
    key: "actions",
    width: 120,
    align: "right",
  },
]);

watch(
  () => brandListQuery.data.value,
  (brands) => {
    if (!selectedBrandId.value && brands?.length) {
      selectedBrandId.value = brands[0].id;
    }
  },
  { immediate: true },
);

watch(
  () => keywordsQuery.data.value,
  (keywords) => {
    if (!keywords?.length) {
      selectedKeywordId.value = null;
      return;
    }

    const stillExists = keywords.some((item) => item.id === selectedKeywordId.value);
    if (!stillExists) {
      selectedKeywordId.value = keywords[0].id;
    }
  },
  { immediate: true },
);

function parseProductLines(value: string): string[] | undefined {
  const lines = value
    .split(",")
    .map((item) => item.trim())
    .filter(Boolean);
  return lines.length ? lines : undefined;
}

function stringifyProductLines(value: unknown): string {
  if (Array.isArray(value)) {
    return value.filter((item) => typeof item === "string").join(", ");
  }
  return "";
}

function openBrandModal(brand?: Brand): void {
  if (!brand && brandLimitReached.value) {
    message.warning(
      t("brands.messages.brandLimitReached", {
        limit: brandLibrarySummary.value?.max_brands ?? 0,
      }),
    );
    return;
  }
  editingBrandId.value = brand?.id ?? null;
  brandForm.name = brand?.name ?? "";
  brandForm.website = brand?.website ?? "";
  brandForm.description = brand?.description ?? "";
  brandModalOpen.value = true;
}

function openKeywordModal(keyword?: Keyword): void {
  if (!selectedBrandId.value) {
    message.warning(t("brands.messages.chooseBrand"));
    return;
  }
  if (!keyword && keywordLimitReached.value) {
    message.warning(
      t("brands.messages.keywordLimitReached", {
        limit: brandLibrarySummary.value?.max_keywords ?? 0,
      }),
    );
    return;
  }
  editingKeywordId.value = keyword?.id ?? null;
  keywordForm.name = keyword?.name ?? "";
  keywordModalOpen.value = true;
}

function openQuestionModal(question?: Question): void {
  if (!selectedBrandId.value) {
    message.warning(t("brands.messages.chooseBrand"));
    return;
  }
  if (!question && questionLimitReached.value) {
    message.warning(
      t("brands.messages.questionLimitReached", {
        limit: brandLibrarySummary.value?.max_questions_per_keyword ?? 0,
      }),
    );
    return;
  }
  editingQuestionId.value = question?.id ?? null;
  questionForm.keyword_id = question?.keyword_id ?? selectedKeywordId.value ?? undefined;
  questionForm.question_text = question?.question_text ?? "";
  questionModalOpen.value = true;
}

function openCompetitorModal(competitor?: Competitor): void {
  if (!selectedBrandId.value) {
    message.warning(t("brands.messages.chooseBrand"));
    return;
  }
  editingCompetitorId.value = competitor?.id ?? null;
  competitorForm.name = competitor?.name ?? "";
  competitorForm.website = competitor?.website ?? "";
  competitorForm.description = competitor?.description ?? "";
  competitorForm.product_lines = stringifyProductLines(competitor?.product_lines_json);
  competitorModalOpen.value = true;
}

async function submitBrand(): Promise<void> {
  if (!brandForm.name.trim()) {
    return;
  }
  if (editingBrandId.value) {
    await brandMutations.update.mutateAsync();
    return;
  }
  await brandMutations.create.mutateAsync();
}

async function submitKeyword(): Promise<void> {
  if (!keywordForm.name.trim()) {
    return;
  }
  if (editingKeywordId.value) {
    await keywordMutations.update.mutateAsync();
    return;
  }
  await keywordMutations.create.mutateAsync();
}

async function submitQuestion(): Promise<void> {
  if (!questionForm.keyword_id) {
    message.warning(t("brands.messages.chooseKeyword"));
    return;
  }
  if (!questionForm.question_text.trim()) {
    return;
  }
  if (editingQuestionId.value) {
    await questionMutations.update.mutateAsync();
    return;
  }
  await questionMutations.create.mutateAsync();
}

async function submitCompetitor(): Promise<void> {
  if (!competitorForm.name.trim()) {
    return;
  }
  if (editingCompetitorId.value) {
    await competitorMutations.update.mutateAsync();
    return;
  }
  await competitorMutations.create.mutateAsync();
}
</script>

<template>
  <div class="brands-view">
    <section class="brands-view__top-card">
      <div class="brands-view__header">
        <div class="brands-view__header-title">
          <h2>{{ t('brands.title') }}</h2>
          <p>{{ t('brands.description') }}</p>
        </div>
        <div class="brands-view__header-actions">
          <a-button type="primary" :disabled="brandLimitReached" @click="openBrandModal()">
            <template #icon><PlusOutlined /></template>
            {{ t("brands.newBrand") }}
          </a-button>
        </div>
      </div>

      <div class="brands-view__quota-strip">
        <div class="brands-view__quota-card brands-view__quota-card--plan">
          <span class="brands-view__quota-label">{{ t("brands.quota.plan") }}</span>
          <strong>{{ brandLibrarySummary?.plan_name || t("shell.planFallback") }}</strong>
          <p>{{ t("brands.quota.planHint") }}</p>
        </div>
        <div class="brands-view__quota-card">
          <span class="brands-view__quota-label">{{ t("brands.quota.brands") }}</span>
          <strong>
            {{ brandLibrarySummary?.used_brands ?? 0 }} / {{ brandLibrarySummary?.max_brands ?? "--" }}
          </strong>
          <p>{{ t("brands.quota.brandsHint") }}</p>
        </div>
        <div class="brands-view__quota-card">
          <span class="brands-view__quota-label">{{ t("brands.quota.keywords") }}</span>
          <strong>
            {{ brandLibrarySummary?.used_keywords ?? 0 }} / {{ brandLibrarySummary?.max_keywords ?? "--" }}
          </strong>
          <p>{{ t("brands.quota.keywordsHint") }}</p>
        </div>
        <div class="brands-view__quota-card">
          <span class="brands-view__quota-label">{{ t("brands.quota.questions") }}</span>
          <strong>{{ brandLibrarySummary?.max_questions_per_keyword ?? "--" }}</strong>
          <p>{{ t("brands.quota.questionsHint") }}</p>
        </div>
      </div>
    </section>

    <section class="brands-view__brand-rail">
      <div class="brands-view__section-head">
        <div>
          <p class="eyebrow">{{ t("brands.railTitle") }}</p>
          <h3>{{ t("brands.railTitle") }}</h3>
        </div>
      </div>

      <div v-if="brandListQuery.data.value?.length" class="brands-view__brand-grid">
        <article
          v-for="brand in brandListQuery.data.value"
          :key="brand.id"
          class="brands-view__brand-card"
          :class="{ 'brands-view__brand-card--active': brand.id === selectedBrandId }"
          @click="selectedBrandId = brand.id"
        >
          <div class="brands-view__brand-card-top">
            <div>
              <h4>{{ brand.name }}</h4>
              <p>{{ brand.description || "--" }}</p>
            </div>

            <div class="brands-view__brand-card-actions">
              <a-tooltip :title="t('common.edit')">
                <a-button
                  type="text"
                  shape="circle"
                  size="small"
                  class="action-btn action-edit"
                  @click.stop="openBrandModal(brand)"
                >
                  <EditOutlined />
                </a-button>
              </a-tooltip>
              <a-popconfirm @confirm="brandMutations.remove.mutate(brand.id)">
                <template #title>{{ t("brands.deleteBrand") }}</template>
                <a-button
                  type="text"
                  shape="circle"
                  size="small"
                  class="action-btn action-delete"
                  :title="t('common.delete')"
                  @click.stop
                >
                  <DeleteOutlined />
                </a-button>
              </a-popconfirm>
            </div>
          </div>

          <div class="brands-view__brand-meta">
            <span>{{ t("brands.meta.keywordCount", { count: brand.keyword_count }) }}</span>
            <span>{{ t("brands.meta.questionCount", { count: brand.question_count }) }}</span>
          </div>
        </article>
      </div>
      <a-empty v-else :description="t('brands.empty.brands')" />
    </section>

    <template v-if="selectedBrandId">
      <a-tabs v-model:activeKey="activeTab" class="brands-view__tabs">
        <a-tab-pane key="keywords" :tab="t('brands.tabs.keywords')">
          <section class="brands-view__keyword-layout">
            <aside class="brands-view__keywords-panel">
              <div class="brands-view__section-head brands-view__section-head--compact">
                <div>
                  <h3>{{ t("brands.sections.keywords") }}</h3>
                  <p class="brands-view__section-hint">
                    {{ t("brands.meta.brandKeywordCount", { count: selectedBrandKeywordCount }) }}
                    <span class="brands-view__dot">·</span>
                    {{ t("brands.meta.globalKeywordUsage", {
                      used: brandLibrarySummary?.used_keywords ?? 0,
                      total: brandLibrarySummary?.max_keywords ?? 0,
                    }) }}
                  </p>
                </div>
                <a-button
                  type="primary"
                  size="small"
                  :disabled="keywordLimitReached"
                  @click="openKeywordModal()"
                >
                  {{ t("brands.actions.newKeyword") }}
                </a-button>
              </div>

              <div v-if="keywordsQuery.data.value?.length" class="brands-view__keyword-list">
                <button
                  v-for="keyword in keywordsQuery.data.value"
                  :key="keyword.id"
                  type="button"
                  class="brands-view__keyword-item"
                  :class="{ 'brands-view__keyword-item--active': keyword.id === selectedKeywordId }"
                  @click="selectedKeywordId = keyword.id"
                >
                  <div class="brands-view__keyword-copy">
                    <span>{{ keyword.name }}</span>
                    <small>
                      {{ t("brands.meta.keywordQuestionUsage", {
                        used: questionCountByKeyword.get(keyword.id) ?? 0,
                        total: brandLibrarySummary?.max_questions_per_keyword ?? 0,
                      }) }}
                    </small>
                  </div>
                  <div class="brands-view__keyword-actions">
                    <a-tooltip :title="t('common.edit')">
                      <a-button
                        type="text"
                        shape="circle"
                        size="small"
                        class="action-btn action-edit"
                        @click.stop="openKeywordModal(keyword)"
                      >
                        <EditOutlined />
                      </a-button>
                    </a-tooltip>
                    <a-popconfirm @confirm="keywordMutations.remove.mutate(keyword.id)">
                      <template #title>{{ t("common.delete") }}</template>
                      <a-button
                        type="text"
                        shape="circle"
                        size="small"
                        class="action-btn action-delete"
                        :title="t('common.delete')"
                        @click.stop
                      >
                        <DeleteOutlined />
                      </a-button>
                    </a-popconfirm>
                  </div>
                </button>
              </div>
              <a-empty v-else :description="t('common.noData')" />
            </aside>

            <section class="brands-view__questions-panel">
              <div class="brands-view__section-head brands-view__section-head--compact">
                <div>
                  <p class="eyebrow">{{ t("brands.sections.questions") }}</p>
                  <h3>{{ selectedKeyword?.name || t("brands.sections.questions") }}</h3>
                  <p class="brands-view__section-hint">
                    {{ t("brands.meta.keywordQuestionUsage", {
                      used: selectedKeywordQuestionCount,
                      total: brandLibrarySummary?.max_questions_per_keyword ?? 0,
                    }) }}
                  </p>
                </div>
                <a-button
                  type="primary"
                  size="small"
                  :disabled="!selectedKeywordId || questionLimitReached"
                  @click="openQuestionModal()"
                >
                  {{ t("brands.actions.newQuestion") }}
                </a-button>
              </div>

              <a-table
                :columns="questionColumns"
                :data-source="filteredQuestionsQuery.data.value || []"
                :loading="filteredQuestionsQuery.isPending.value"
                :pagination="false"
                row-key="id"
              >
                <template #emptyText>{{ t("brands.empty.questions") }}</template>
                <template #bodyCell="{ column, record }">
                  <template v-if="column.key === 'question_text'">
                    <div class="brands-view__question-cell">
                      <strong>{{ record.question_text }}</strong>
                    </div>
                  </template>
                  <template v-else-if="column.key === 'created_at'">
                    <span class="brands-view__datetime">{{ formatDateTime(record.created_at) }}</span>
                  </template>
                  <template v-else-if="column.key === 'actions'">
                    <div class="table-actions-row">
                      <a-tooltip :title="t('common.edit')">
                        <a-button
                          type="text"
                          shape="circle"
                          size="small"
                          class="action-btn action-edit"
                          @click="openQuestionModal(record)"
                        >
                          <EditOutlined />
                        </a-button>
                      </a-tooltip>
                      <a-popconfirm @confirm="questionMutations.remove.mutate(record.id)">
                        <template #title>{{ t("common.delete") }}</template>
                        <a-button
                          type="text"
                          shape="circle"
                          size="small"
                          class="action-btn action-delete"
                          :title="t('common.delete')"
                        >
                          <DeleteOutlined />
                        </a-button>
                      </a-popconfirm>
                    </div>
                  </template>
                </template>
              </a-table>
            </section>
          </section>
        </a-tab-pane>

        <a-tab-pane key="competitors" :tab="t('brands.tabs.competitors')">
          <section class="brands-view__competitors-panel">
            <div class="brands-view__section-head brands-view__section-head--compact">
              <div>
                <p class="eyebrow">{{ t("brands.sections.competitors") }}</p>
                <h3>{{ t("brands.sections.competitors") }}</h3>
              </div>
              <a-button type="primary" size="small" @click="openCompetitorModal()">
                {{ t("brands.actions.newCompetitor") }}
              </a-button>
            </div>

            <div v-if="competitorsQuery.data.value?.length" class="brands-view__competitor-grid">
              <article
                v-for="competitor in competitorsQuery.data.value"
                :key="competitor.id"
                class="brands-view__competitor-card"
              >
                <div class="brands-view__competitor-head">
                  <div>
                    <h4>{{ competitor.name }}</h4>
                    <a :href="competitor.website || undefined" target="_blank" rel="noreferrer">
                      {{ competitor.website || "--" }}
                    </a>
                  </div>
                  <div class="brands-view__inline-actions">
                    <a-tooltip :title="t('common.edit')">
                      <a-button
                        type="text"
                        shape="circle"
                        size="small"
                        class="action-btn action-edit"
                        @click="openCompetitorModal(competitor)"
                      >
                        <EditOutlined />
                      </a-button>
                    </a-tooltip>
                    <a-popconfirm @confirm="competitorMutations.remove.mutate(competitor.id)">
                      <template #title>{{ t("common.delete") }}</template>
                      <a-button
                        type="text"
                        shape="circle"
                        size="small"
                        class="action-btn action-delete"
                        :title="t('common.delete')"
                      >
                        <DeleteOutlined />
                      </a-button>
                    </a-popconfirm>
                  </div>
                </div>
                <p>{{ competitor.description || "--" }}</p>
                <div class="brands-view__competitor-lines">
                  <span
                    v-for="line in Array.isArray(competitor.product_lines_json)
                      ? competitor.product_lines_json
                      : []"
                    :key="String(line)"
                  >
                    {{ line }}
                  </span>
                </div>
              </article>
            </div>
            <a-empty v-else :description="t('brands.empty.competitors')" />
          </section>
        </a-tab-pane>
      </a-tabs>
    </template>

    <a-modal
      v-model:open="brandModalOpen"
      :title="editingBrandId ? t('brands.editBrand') : t('brands.newBrand')"
      centered
      @ok="submitBrand"
    >
      <a-form layout="vertical">
        <a-form-item :label="t('brands.form.brandName')">
          <a-input v-model:value="brandForm.name" />
        </a-form-item>
        <a-form-item :label="t('brands.form.brandWebsite')">
          <a-input v-model:value="brandForm.website" />
        </a-form-item>
        <a-form-item :label="t('brands.form.brandDescription')">
          <a-textarea v-model:value="brandForm.description" :rows="4" />
        </a-form-item>
      </a-form>
    </a-modal>

    <a-modal
      v-model:open="keywordModalOpen"
      :title="editingKeywordId ? t('common.edit') : t('brands.actions.newKeyword')"
      centered
      @ok="submitKeyword"
    >
      <a-form layout="vertical">
        <a-form-item :label="t('brands.form.keywordName')">
          <a-input v-model:value="keywordForm.name" />
        </a-form-item>
      </a-form>
    </a-modal>

    <a-modal
      v-model:open="questionModalOpen"
      :title="editingQuestionId ? t('common.edit') : t('brands.actions.newQuestion')"
      centered
      @ok="submitQuestion"
    >
      <a-form layout="vertical">
        <a-form-item :label="t('brands.sections.keywords')">
          <a-select
            v-model:value="questionForm.keyword_id"
            :options="(keywordsQuery.data.value || []).map((item) => ({ label: item.name, value: item.id }))"
          />
        </a-form-item>
        <a-form-item :label="t('brands.form.questionText')">
          <a-textarea v-model:value="questionForm.question_text" :rows="4" />
        </a-form-item>
      </a-form>
    </a-modal>

    <a-modal
      v-model:open="competitorModalOpen"
      :title="editingCompetitorId ? t('common.edit') : t('brands.actions.newCompetitor')"
      centered
      @ok="submitCompetitor"
    >
      <a-form layout="vertical">
        <a-form-item :label="t('brands.form.competitorName')">
          <a-input v-model:value="competitorForm.name" />
        </a-form-item>
        <a-form-item :label="t('brands.form.competitorWebsite')">
          <a-input v-model:value="competitorForm.website" />
        </a-form-item>
        <a-form-item :label="t('brands.form.competitorDescription')">
          <a-textarea v-model:value="competitorForm.description" :rows="3" />
        </a-form-item>
        <a-form-item :label="t('brands.form.competitorLines')">
          <a-input
            v-model:value="competitorForm.product_lines"
            :placeholder="t('brands.form.competitorLinesHint')"
          />
        </a-form-item>
      </a-form>
    </a-modal>
  </div>
</template>

<style scoped>
.brands-view {
  display: flex;
  flex-direction: column;
  gap: 22px;
}

.brands-view__top-card,
.brands-view__brand-rail,
.brands-view__keywords-panel,
.brands-view__questions-panel,
.brands-view__competitors-panel {
  padding: 24px;
  background: #fff;
  border: 1px solid #e6edf5;
  border-radius: 12px;
  overflow: hidden;
}

.brands-view__top-card {
  padding: 0;
}

.brands-view__header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 24px;
}

.brands-view__quota-strip {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
  padding: 0 24px 24px;
  border-top: 1px solid #eef3f8;
}

.brands-view__quota-card {
  padding: 16px 18px;
  border: 1px solid #e6edf5;
  border-radius: 12px;
  background: linear-gradient(180deg, #ffffff 0%, #f7fbff 100%);
}

.brands-view__quota-card--plan {
  background: linear-gradient(135deg, #eff6ff 0%, #ffffff 100%);
  border-color: #cfe0ff;
}

.brands-view__quota-label {
  display: block;
  margin-bottom: 8px;
  font-size: 12px;
  letter-spacing: 0.04em;
  color: #6b7280;
  text-transform: uppercase;
}

.brands-view__quota-card strong {
  display: block;
  font-size: 22px;
  line-height: 1.2;
  color: #111827;
}

.brands-view__quota-card p {
  margin: 8px 0 0;
  color: #6b7280;
  font-size: 13px;
  line-height: 1.5;
}

.brands-view__header-title h2 {
  margin: 0;
  font-size: 20px;
  font-weight: 600;
  color: #1a1a1a;
  line-height: 1.4;
}

.brands-view__header-title p {
  margin: 6px 0 0 0;
  font-size: 13px;
  color: #8c8c8c;
}

.brands-view__header-actions {
  display: flex;
  gap: 12px;
  margin-left: auto; /* explicit push to right just in case */
}

.brands-view__section-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
}

.brands-view__section-head h3 {
  margin: 6px 0 0;
  font-size: 20px;
  font-weight: 800;
  color: #111827;
  display: flex;
  align-items: center;
}

.brands-view__section-head h3::before {
  content: "";
  display: inline-block;
  width: 4px;
  height: 18px;
  border-radius: 2px;
  background: #1f5cff;
  margin-right: 12px;
}

.brands-view__section-head--compact h3 {
  font-size: 18px;
}

.brands-view__section-head--compact h3::before {
  height: 16px;
}

.brands-view__section-hint {
  margin: 8px 0 0;
  color: #6b7280;
  font-size: 13px;
}

.brands-view__dot {
  margin: 0 8px;
  color: #c0cad8;
}

.brands-view__brand-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}

.brands-view__brand-card {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 18px;
  background: #fff;
  border: 1px solid #e6edf5;
  border-radius: 12px;
  cursor: pointer;
  transition: transform 0.2s, box-shadow 0.2s;
}

.brands-view__brand-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 24px rgba(0,0,0,0.06);
}

.brands-view__brand-card-actions,
.brands-view__keyword-actions,
.brands-view__competitor-head .brands-view__inline-actions {
  opacity: 0;
  transition: opacity 0.2s ease;
}

.brands-view__brand-card:hover .brands-view__brand-card-actions,
.brands-view__brand-card:focus-within .brands-view__brand-card-actions,
.brands-view__keyword-item:hover .brands-view__keyword-actions,
.brands-view__keyword-item:focus-within .brands-view__keyword-actions,
.brands-view__competitor-card:hover .brands-view__competitor-head .brands-view__inline-actions,
.brands-view__competitor-card:focus-within .brands-view__competitor-head .brands-view__inline-actions {
  opacity: 1;
}

.brands-view__brand-card--active {
  border-color: #bfd7ff;
  background: #f0f7ff;
  box-shadow: 0 18px 40px rgba(31, 92, 255, 0.08);
}

.brands-view__brand-card-top {
  display: flex;
  justify-content: space-between;
  gap: 12px;
}

.brands-view__brand-card h4,
.brands-view__competitor-card h4 {
  margin: 0;
}

.brands-view__brand-card p,
.brands-view__competitor-card p {
  margin: 8px 0 0;
  color: var(--muted);
  line-height: 1.6;
}

.brands-view__brand-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.brands-view__brand-meta span {
  padding: 6px 10px;
  border-radius: 999px;
  background: #edf4ff;
  color: #2458d3;
  font-size: 12px;
  font-weight: 600;
}

.brands-view__brand-card-actions,
.brands-view__keyword-actions,
.brands-view__inline-actions {
  display: flex;
  align-items: center;
  gap: 4px;
}

.brands-view__keyword-layout {
  display: grid;
  grid-template-columns: 320px minmax(0, 1fr);
  gap: 20px;
}

.brands-view__keyword-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.brands-view__keyword-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 16px;
  background: #fff;
  border: 1px solid #e6edf5;
  border-radius: 12px;
  cursor: pointer;
  text-align: left;
  transition: all 0.2s;
}

.brands-view__keyword-copy {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.brands-view__keyword-copy span {
  font-weight: 600;
  color: #111827;
}

.brands-view__keyword-copy small {
  color: #6b7280;
  font-size: 12px;
}

.brands-view__keyword-item:hover {
  border-color: #bfd7ff;
  background: #f0f7ff;
}

.brands-view__keyword-item--active {
  border-color: #bfd7ff;
  background: #eef5ff;
}

.brands-view__question-cell {
  display: flex;
  flex-direction: column;
}

.brands-view__datetime {
  white-space: nowrap;
}

.brands-view__competitor-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}

.brands-view__competitor-card {
  padding: 18px;
  background: #fff;
  border: 1px solid #e6edf5;
  border-radius: 12px;
  transition: transform 0.2s, box-shadow 0.2s;
}

.brands-view__competitor-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 24px rgba(0,0,0,0.06);
}

.brands-view__competitor-head {
  display: flex;
  justify-content: space-between;
  gap: 12px;
}

.brands-view__competitor-head a {
  color: #1f5cff;
  font-size: 13px;
}

.brands-view__competitor-lines {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 14px;
}

.brands-view__competitor-lines span {
  padding: 6px 10px;
  background: #e8f0ff;
  border-radius: 999px;
  color: #1f5cff;
  font-size: 12px;
}

@media (max-width: 1080px) {
  .brands-view__quota-strip,
  .brands-view__brand-grid,
  .brands-view__keyword-layout,
  .brands-view__competitor-grid {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 720px) {
  .brands-view__header,
  .brands-view__section-head {
    flex-direction: column;
    align-items: stretch;
  }
}
</style>
