<template>
  <section
    class="settings-section"
    id="settings-section_page"
    data-color-type="page"
  >
    <h2>Réglage des pages</h2>
    <div class="container">
      <div class="settings-subsection">
        <div class="field field-simple">
          <label for="page-format" class="label-with-tooltip" data-css="size"
            >Format d'impression</label
          >
          <select id="page-format" v-model="pageFormat">
            <option value="A4">A4</option>
            <option value="A5">A5</option>
            <!-- <option value="A3">A3</option>
          <option value="letter">Letter</option>
          <option value="legal">Legal</option> -->
            <option value="custom">Personnalisé</option>
          </select>
        </div>
      </div>

      <div class="settings-subsection">
        <div
          class="field field-margin"
          :class="{ 'field--view-only': !isCustomFormat }"
        >
          <label for="page-width" class="label-with-tooltip" data-css="width"
            >Largeur</label
          >
          <div class="input-with-unit">
            <NumberInput
              id="page-width"
              :modelValue="customWidth"
              @update:modelValue="(v) => (customWidth = v)"
              :min="50"
              :step="1"
              :disabled="!isCustomFormat"
            />
            <div class="unit-toggle">
              <button type="button" class="active">mm</button>
            </div>
          </div>
        </div>

        <div
          class="field field-margin"
          :class="{ 'field--view-only': !isCustomFormat }"
        >
          <label for="page-height" class="label-with-tooltip" data-css="height"
            >Hauteur</label
          >
          <div class="input-with-unit">
            <NumberInput
              id="page-height"
              :modelValue="customHeight"
              @update:modelValue="(v) => (customHeight = v)"
              :min="50"
              :step="1"
              :disabled="!isCustomFormat"
            />
            <div class="unit-toggle">
              <button type="button" class="active">mm</button>
            </div>
          </div>
        </div>
      </div>

      <div class="settings-subsection margins">
        <h3>Marges</h3>

        <div class="field field-margin">
          <label
            for="margin-top"
            class="label-with-tooltip"
            data-css="margin-top"
            >Haut</label
          >
          <div class="input-with-unit">
            <NumberInput
              id="margin-top"
              :modelValue="margins.top.value"
              :min="0"
              :step="1"
              @update:modelValue="(value) => (margins.top.value = value)"
            />
            <div class="unit-toggle">
              <button
                type="button"
                :class="{ active: margins.top.unit === 'mm' }"
                @click="updateMarginUnit('top', 'mm')"
              >
                mm
              </button>
              <button
                type="button"
                :class="{ active: margins.top.unit === 'px' }"
                @click="updateMarginUnit('top', 'px')"
              >
                px
              </button>
              <!-- <button
              type="button"
              :class="{ active: margins.top.unit === 'rem' }"
              @click="updateMarginUnit('top', 'rem')"
            >
              rem
            </button> -->
            </div>
          </div>
        </div>

        <div class="field field-margin">
          <label
            for="margin-bottom"
            class="label-with-tooltip"
            data-css="margin-bottom"
            >Bas</label
          >
          <div class="input-with-unit">
            <NumberInput
              id="margin-bottom"
              :modelValue="margins.bottom.value"
              :min="0"
              :step="1"
              @update:modelValue="(value) => (margins.bottom.value = value)"
            />
            <div class="unit-toggle">
              <button
                type="button"
                :class="{ active: margins.bottom.unit === 'mm' }"
                @click="updateMarginUnit('bottom', 'mm')"
              >
                mm
              </button>
              <button
                type="button"
                :class="{ active: margins.bottom.unit === 'px' }"
                @click="updateMarginUnit('bottom', 'px')"
              >
                px
              </button>
              <!-- <button
              type="button"
              :class="{ active: margins.bottom.unit === 'rem' }"
              @click="updateMarginUnit('bottom', 'rem')"
            >
              rem
            </button> -->
            </div>
          </div>
        </div>

        <div class="field field-margin">
          <label
            for="margin-left"
            class="label-with-tooltip"
            data-css="margin-left"
            >Gauche</label
          >
          <div class="input-with-unit">
            <NumberInput
              id="margin-left"
              :modelValue="margins.left.value"
              :min="0"
              :step="1"
              @update:modelValue="(value) => (margins.left.value = value)"
            />
            <div class="unit-toggle">
              <button
                type="button"
                :class="{ active: margins.left.unit === 'mm' }"
                @click="updateMarginUnit('left', 'mm')"
              >
                mm
              </button>
              <button
                type="button"
                :class="{ active: margins.left.unit === 'px' }"
                @click="updateMarginUnit('left', 'px')"
              >
                px
              </button>
              <!-- <button
              type="button"
              :class="{ active: margins.left.unit === 'rem' }"
              @click="updateMarginUnit('left', 'rem')"
            >
              rem
            </button> -->
            </div>
          </div>
        </div>

        <div class="field field-margin">
          <label
            for="margin-right"
            class="label-with-tooltip"
            data-css="margin-right"
            >Droite</label
          >
          <div class="input-with-unit">
            <NumberInput
              id="margin-right"
              :modelValue="margins.right.value"
              :min="0"
              :step="1"
              @update:modelValue="(value) => (margins.right.value = value)"
            />
            <div class="unit-toggle">
              <button
                type="button"
                :class="{ active: margins.right.unit === 'mm' }"
                @click="updateMarginUnit('right', 'mm')"
              >
                mm
              </button>
              <button
                type="button"
                :class="{ active: margins.right.unit === 'px' }"
                @click="updateMarginUnit('right', 'px')"
              >
                px
              </button>
              <!-- <button
              type="button"
              :class="{ active: margins.right.unit === 'rem' }"
              @click="updateMarginUnit('right', 'rem')"
            >
              rem
            </button> -->
            </div>
          </div>
        </div>
      </div>

      <div class="settings-subsection">
        <div class="field field-simple">
          <label
            for="background"
            class="label-with-tooltip"
            data-css="background"
            >Arrière-plan</label
          >
          <div class="input-with-color">
            <input
              ref="backgroundColorInput"
              type="text"
              id="background"
              v-model="background.value"
              data-coloris
            />
            <!-- Temporarily commented out
          <div class="unit-toggle">
            <button
              type="button"
              :class="{ active: background.format === 'rgb' }"
              @click="background.format = 'rgb'"
            >
              rgb
            </button>
            <button
              type="button"
              :class="{ active: background.format === 'hex' }"
              @click="background.format = 'hex'"
            >
              hex
            </button>
          </div>
          --></div>
        </div>
      </div>

      <div class="settings-subsection" title="Fonctionnalité à venir">
        <div class="field field-simple field--view-only">
          <label
            for="pattern"
            class="label-with-tooltip"
            data-css="background-image"
            >Motif</label
          >
          <select id="pattern" v-model="pattern" disabled>
            <option value="">Choisissez</option>
            <option value="dots">Points</option>
            <option value="lines">Lignes</option>
            <option value="grid">Grille</option>
          </select>
        </div>
      </div>

      <div class="settings-subsection">
        <div class="field checkbox-field">
          <input id="page-numbers" type="checkbox" v-model="pageNumbers" />
          <label
            for="page-numbers"
            class="label-with-tooltip"
            data-css="@bottom-left/right"
            >Numéro de page</label
          >
        </div>

        <div class="field checkbox-field">
          <input id="running-title" type="checkbox" v-model="runningTitle" />
          <label
            for="running-title"
            class="label-with-tooltip"
            data-css="string-set"
            >Titre courant</label
          >
        </div>
      </div>
    </div>
  </section>
</template>

<script setup>
import { ref, computed, watch, onMounted, inject } from 'vue';
import { useStylesheetStore } from '../../stores/stylesheet';
import { useDebounce } from '../../composables/useDebounce';
import { useCssSync } from '../../composables/useCssSync';
import { initColoris } from '../../composables/useColoris';
import NumberInput from '../ui/NumberInput.vue';
import { convertUnit } from '../../utils/unit-conversion';

const stylesheetStore = useStylesheetStore();
const { debouncedUpdate } = useDebounce(500);
const { extractSpacing } = useCssSync();
const backgroundColorInput = ref(null);
const activeTab = inject('activeTab', ref('document'));

let isUpdatingFromStore = false;

const pageFormat = ref('A4');

const pageFormats = {
  A4: { width: 210, height: 297 },
  A5: { width: 148, height: 210 },
  // A3: { width: 297, height: 420 },
  // letter: { width: 216, height: 279 },
  // legal: { width: 216, height: 356 },
};

const customWidth = ref(210);
const customHeight = ref(297);
const isCustomFormat = computed(() => pageFormat.value === 'custom');

const margins = ref({
  top: { value: 20, unit: 'mm' },
  bottom: { value: 20, unit: 'mm' },
  left: { value: 20, unit: 'mm' },
  right: { value: 20, unit: 'mm' },
});

const updateMarginUnit = (side, newUnit) => {
  const m = margins.value[side];
  m.value = convertUnit(m.value, m.unit, newUnit);
  m.unit = newUnit;
};

const background = ref({
  value: '',
  format: 'hex',
});

const pattern = ref('');
const pageNumbers = ref(false);
const runningTitle = ref(false);

const immediateUpdate = (callback) => {
  callback();
};

watch(pageFormat, (newFormat) => {
  if (isUpdatingFromStore) return;

  if (newFormat === 'custom') {
    immediateUpdate(() => {
      stylesheetStore.updateProperty(
        '@page',
        'size',
        `${customWidth.value}mm ${customHeight.value}mm`,
        ''
      );
    });
  } else {
    const format = pageFormats[newFormat];
    if (format) {
      customWidth.value = format.width;
      customHeight.value = format.height;
    }
    immediateUpdate(() => {
      stylesheetStore.updateProperty('@page', 'size', newFormat, '');
    });
  }
});

watch([customWidth, customHeight], () => {
  if (isUpdatingFromStore || !isCustomFormat.value) return;
  debouncedUpdate(() => {
    stylesheetStore.updateProperty(
      '@page',
      'size',
      `${customWidth.value}mm ${customHeight.value}mm`,
      ''
    );
  });
});

const updateMargins = () => {
  const marginValue = `${margins.value.top.value}${margins.value.top.unit} ${margins.value.right.value}${margins.value.right.unit} ${margins.value.bottom.value}${margins.value.bottom.unit} ${margins.value.left.value}${margins.value.left.unit}`;

  const currentBlock = stylesheetStore.extractBlock('@page');
  const updatedBlock = currentBlock.replace(
    /(margin:\s*)[^;]+/,
    `$1${marginValue}`
  );

  stylesheetStore.replaceBlock(currentBlock, updatedBlock);
};

// Watch margin values (number inputs) with debounce
watch(
  () => [
    margins.value.top.value,
    margins.value.bottom.value,
    margins.value.left.value,
    margins.value.right.value,
  ],
  () => {
    if (isUpdatingFromStore) return;
    debouncedUpdate(updateMargins);
  }
);

// Watch margin units (button clicks) without debounce
watch(
  () => [
    margins.value.top.unit,
    margins.value.bottom.unit,
    margins.value.left.unit,
    margins.value.right.unit,
  ],
  () => {
    if (isUpdatingFromStore) return;
    immediateUpdate(updateMargins);
  }
);

const updateBackground = () => {
  if (!background.value.value) return;

  const currentBlock = stylesheetStore.extractBlock('@page');

  if (currentBlock.includes('background:')) {
    const updatedBlock = currentBlock.replace(
      /(background:\s*)[^;]+/,
      `$1${background.value.value}`
    );
    stylesheetStore.replaceBlock(currentBlock, updatedBlock);
  } else {
    const updatedBlock = currentBlock.replace(
      /(\s*})$/,
      `  background: ${background.value.value};\n$1`
    );
    stylesheetStore.replaceBlock(currentBlock, updatedBlock);
  }
};

// Watch background value (text input) with debounce
watch(
  () => background.value.value,
  () => {
    if (isUpdatingFromStore) return;
    debouncedUpdate(updateBackground);
  }
);

// Watch background format (button clicks) without debounce
watch(
  () => background.value.format,
  () => {
    if (isUpdatingFromStore) return;
    immediateUpdate(updateBackground);
  }
);

watch(pattern, (newPattern) => {
  if (!newPattern || isUpdatingFromStore) return;

  immediateUpdate(() => {
    // TODO: implement pattern application
  });
});

watch(pageNumbers, (enabled) => {
  if (isUpdatingFromStore) return;

  immediateUpdate(() => {
    updatePageFooters();
  });
});

watch(runningTitle, (enabled) => {
  if (isUpdatingFromStore) return;

  immediateUpdate(() => {
    updatePageFooters();
  });
});

const updatePageFooters = () => {
  let currentCss = stylesheetStore.customCss;

  // Remove existing @page:left and @page:right rules
  currentCss = currentCss.replace(/@page:left\s*\{[^}]*\}/g, '');
  currentCss = currentCss.replace(/@page:right\s*\{[^}]*\}/g, '');

  // Remove old @page @bottom-center rule if exists
  currentCss = currentCss.replace(
    /@page\s*\{[^}]*@bottom-center[^}]*\}/g,
    (match) => {
      return match.replace(/@bottom-center\s*\{[^}]*\}/g, '');
    }
  );

  // Remove string-set rule if running title is disabled
  if (!runningTitle.value) {
    currentCss = currentCss.replace(
      /\.chapter\s*>\s*h2\s*\{[^}]*string-set:[^}]*\}\s*/g,
      ''
    );
  } else if (!currentCss.includes('string-set: title')) {
    // Add the string-set rule for h2 titles if running title is enabled
    const stringSetRule =
      '\n.chapter > h2 {\n  string-set: title content(text);\n}\n';
    currentCss += stringSetRule;
  }

  // Build new rules based on checkboxes
  let leftPageRule = '';
  let rightPageRule = '';

  if (pageNumbers.value || runningTitle.value) {
    // Left pages: page number bottom-left, running title right next to it (bottom-left-corner)
    let leftBottomLeft = '';
    let leftBottomCenter = '';

    if (pageNumbers.value && runningTitle.value) {
      // Page number on the left, title right next to it
      leftBottomLeft =
        '  @bottom-left {\n    content: counter(page) " " string(title);\n  }\n';
    } else if (pageNumbers.value) {
      leftBottomLeft = '  @bottom-left {\n    content: counter(page);\n  }\n';
    } else if (runningTitle.value) {
      leftBottomLeft = '  @bottom-left {\n    content: string(title);\n  }\n';
    }

    if (leftBottomLeft || leftBottomCenter) {
      leftPageRule = `@page:left {\n${leftBottomLeft}${leftBottomCenter}}\n\n`;
    }

    // Right pages: title on the left, page number on the right (next to it)
    let rightBottomRight = '';

    if (pageNumbers.value && runningTitle.value) {
      // Title on the left of page number
      rightBottomRight =
        '  @bottom-right {\n    content: string(title) " " counter(page);\n  }\n';
    } else if (pageNumbers.value) {
      rightBottomRight =
        '  @bottom-right {\n    content: counter(page);\n  }\n';
    } else if (runningTitle.value) {
      rightBottomRight =
        '  @bottom-right {\n    content: string(title);\n  }\n';
    }

    if (rightBottomRight) {
      rightPageRule = `@page:right {\n${rightBottomRight}}\n\n`;
    }
  }

  // Insert the new rules after the main @page rule
  const pageRuleMatch = currentCss.match(/@page\s*\{[^}]*\}/);
  if (pageRuleMatch) {
    const insertPosition = pageRuleMatch.index + pageRuleMatch[0].length;
    currentCss =
      currentCss.slice(0, insertPosition) +
      '\n\n' +
      leftPageRule +
      rightPageRule +
      currentCss.slice(insertPosition);
  }

  stylesheetStore.setCustomCss(currentCss);
};

const syncFromStore = () => {
  isUpdatingFromStore = true;

  try {
    const pageBlock = stylesheetStore.extractBlock('@page');

    // Try named format first (A4, A5), then custom dimensions
    const namedSizeMatch = pageBlock.match(/size:\s*(A4|A5)\b/);
    if (namedSizeMatch) {
      pageFormat.value = namedSizeMatch[1];
      const format = pageFormats[namedSizeMatch[1]];
      if (format) {
        customWidth.value = format.width;
        customHeight.value = format.height;
      }
    } else {
      const customSizeMatch = pageBlock.match(
        /size:\s*([0-9.]+)mm\s+([0-9.]+)mm/
      );
      if (customSizeMatch) {
        customWidth.value = parseFloat(customSizeMatch[1]);
        customHeight.value = parseFloat(customSizeMatch[2]);
        pageFormat.value = 'custom';
      }
    }

    const spacing = extractSpacing('@page', 'margin');
    if (spacing?.detailed) {
      margins.value.top = spacing.detailed.top;
      margins.value.right = spacing.detailed.right;
      margins.value.bottom = spacing.detailed.bottom;
      margins.value.left = spacing.detailed.left;
    } else if (spacing?.simple) {
      margins.value.top = { ...spacing.simple };
      margins.value.right = { ...spacing.simple };
      margins.value.bottom = { ...spacing.simple };
      margins.value.left = { ...spacing.simple };
    }

    const bgMatch = pageBlock.match(/background:\s*([^;]+)/);
    if (bgMatch) {
      background.value.value = bgMatch[1].trim();
    }

    // Check for page numbers and running title in @page:left and @page:right
    const leftPageMatch = stylesheetStore.content.match(
      /@page:left\s*\{[^}]*\}/
    );
    const rightPageMatch = stylesheetStore.content.match(
      /@page:right\s*\{[^}]*\}/
    );

    // Check if page numbers exist (counter(page) in either left or right)
    const hasPageNumbers =
      (leftPageMatch && leftPageMatch[0].includes('counter(page)')) ||
      (rightPageMatch && rightPageMatch[0].includes('counter(page)'));
    pageNumbers.value = hasPageNumbers;

    // Check if running title exists (string(title) in either left or right)
    const hasRunningTitle =
      (leftPageMatch && leftPageMatch[0].includes('string(title)')) ||
      (rightPageMatch && rightPageMatch[0].includes('string(title)'));
    runningTitle.value = hasRunningTitle;
  } finally {
    isUpdatingFromStore = false;
  }
};

watch(
  () => stylesheetStore.content,
  () => {
    if (!isUpdatingFromStore) {
      syncFromStore();
    }
  }
);

const updateColorisButton = () => {
  const input = backgroundColorInput.value;
  if (input && background.value.value) {
    // Force Coloris to update by triggering a change event
    const event = new Event('input', { bubbles: true });
    input.dispatchEvent(event);
  }
};

// Watch for when the user returns to the "document" tab
watch(activeTab, (newTab, oldTab) => {
  if (
    newTab === 'document' &&
    oldTab !== 'document' &&
    background.value.value
  ) {
    // Small delay to ensure DOM is ready
    setTimeout(updateColorisButton, 100);
  }
});

onMounted(() => {
  syncFromStore();

  initColoris();

  // Initialize button color if value exists
  if (background.value.value) {
    setTimeout(updateColorisButton, 100);
  }
});
</script>
