<template>
  <div class="manage-accounts min-vh-100 bg-light pb-5">
    <header class="header-premium text-white py-4 shadow-sm position-relative overflow-hidden mb-4 bg-primary-gradient">
      <div class="container position-relative z-2">
        <div class="d-flex align-items-center gap-4">
          <div class="bg-white rounded-circle p-3 shadow">
            <i class="fas fa-sitemap fa-2x text-primary"></i>
          </div>
          <div>
            <h2 class="fw-bold text-white mb-0">Manage Accounts</h2>
            <p class="text-white-50 small text-uppercase ls-wide mt-1">Chart of Accounts</p>
          </div>
        </div>
      </div>
    </header>

    <div class="container">

      <!-- Store selector (store owner / store manager only) -->
      <div v-if="stores.length > 0" class="mb-3">
        <div class="d-flex align-items-center gap-2 flex-wrap">
          <label class="fw-semibold small text-muted mb-0">Store:</label>
          <div class="d-flex gap-2 flex-wrap">
            <button
              v-for="s in stores"
              :key="s.hashkey"
              class="btn btn-sm"
              :class="selectedStoreId === s.id ? 'btn-primary' : 'btn-outline-secondary'"
              @click="selectStore(s)"
            >
              <i class="fas fa-store me-1"></i>{{ s.name }}
            </button>
          </div>
        </div>
      </div>

      <!-- Accounting Theme Panel (Big 3 only) -->
      <div v-if="isBig3" class="card border-0 shadow-sm rounded-4 bg-white mb-3">
        <div
          class="card-header bg-white border-0 d-flex align-items-center justify-content-between py-3 px-3"
          style="cursor:pointer"
          @click="themeOpen = !themeOpen"
        >
          <div class="d-flex align-items-center gap-2">
            <i class="fas fa-palette text-primary"></i>
            <span class="fw-bold small">Accounting Theme</span>
            <span v-if="themeInfo" class="badge bg-primary-subtle text-primary small ms-1">{{ themeInfo.definition.label }}</span>
          </div>
          <i class="fas text-muted" :class="themeOpen ? 'fa-chevron-up' : 'fa-chevron-down'"></i>
        </div>

        <div v-if="themeOpen" class="card-body pt-0 px-3 pb-3">
          <div v-if="loadingThemes" class="text-center py-3 text-muted small">
            <i class="fas fa-circle-notch fa-spin me-1"></i> Loading themes…
          </div>
          <div v-else-if="themeInfo">
            <div class="row g-2 mb-3">
              <div v-for="opt in themeInfo.options" :key="opt.key" class="col-6 col-md-4 col-lg-3">
                <div
                  class="p-2 rounded-3 border h-100"
                  :class="opt.key === themeInfo.current ? 'border-primary border-2 bg-primary-subtle' : (opt.key === selectThemeKey ? 'border-primary' : 'border-light-subtle bg-light')"
                  style="cursor:pointer; font-size:.82rem"
                  @click="selectThemeKey = opt.key"
                >
                  <div class="d-flex align-items-center gap-1 mb-1">
                    <i class="fas fa-palette text-primary" style="font-size:.7rem"></i>
                    <span class="fw-bold">{{ opt.label }}</span>
                    <span v-if="opt.key === themeInfo.current" class="badge bg-primary ms-auto" style="font-size:.6rem">Active</span>
                  </div>
                  <div class="text-muted" style="font-size:.72rem; line-height:1.3">{{ opt.description }}</div>
                </div>
              </div>
            </div>

            <div class="d-flex flex-wrap align-items-center gap-3 p-2 bg-light rounded-3 small">
              <span class="text-muted">Theme accounts: <strong>{{ themeInfo.counts.theme_tagged }}</strong></span>
              <span class="text-muted">User-added: <strong>{{ themeInfo.counts.user_added }}</strong></span>
              <span v-if="themeDrift && themeDrift.totals.missing > 0" class="text-warning">
                <i class="fas fa-exclamation-triangle me-1"></i>Missing: <strong>{{ themeDrift.totals.missing }}</strong>
              </span>
              <div class="ms-auto d-flex gap-2">
                <button
                  class="btn btn-outline-primary btn-sm"
                  :disabled="!selectThemeKey || selectThemeKey === themeInfo.current || switchingTheme"
                  @click="switchTheme"
                >
                  <i class="fas fa-shuffle me-1"></i>{{ switchingTheme ? 'Switching…' : 'Switch' }}
                </button>
                <button
                  class="btn btn-primary btn-sm"
                  :disabled="applyingTheme"
                  @click="reapplyTheme"
                >
                  <i class="fas fa-sync me-1" :class="{ 'fa-spin': applyingTheme }"></i>
                  {{ applyingTheme ? 'Applying…' : 'Apply theme' }}
                </button>
              </div>
            </div>
            <p class="text-muted mt-2 mb-0" style="font-size:.75rem">
              <i class="fas fa-info-circle me-1"></i>
              Switching only changes which theme is tracked — it does not seed accounts. Apply is additive: never deletes or renames.
            </p>
          </div>
        </div>
      </div>

      <!-- Toolbar -->
      <div class="d-flex justify-content-between align-items-center mb-3 flex-wrap gap-2">
        <h4 class="fw-bold mb-0"><i class="fas fa-folder-tree text-primary me-2"></i> Hierarchy</h4>
        <div class="d-flex gap-2 flex-wrap">
          <button class="btn btn-outline-secondary btn-sm" @click="includeArchived = !includeArchived">
            <i class="fas" :class="includeArchived ? 'fa-eye-slash' : 'fa-eye'"></i>
            {{ includeArchived ? 'Hide archived' : 'Show archived' }}
          </button>
          <button class="btn btn-primary btn-sm" @click="openCreate(null)">
            <i class="fas fa-plus me-1"></i> Add root account
          </button>
        </div>
      </div>

      <div class="card border-0 shadow-lg rounded-4 bg-white">
        <div class="card-body p-3">
          <div v-if="loading" class="text-center text-muted py-4">
            <i class="fas fa-circle-notch fa-spin me-2"></i> Loading…
          </div>
          <div v-else-if="visibleTree.length === 0" class="text-center text-muted py-5">
            <i class="fas fa-inbox fa-2x mb-2 d-block"></i>
            No accounts yet. Click <strong>Add root account</strong> to get started.
          </div>
          <ul v-else class="list-unstyled mb-0">
            <AccountNode
              v-for="node in visibleTree"
              :key="node.id"
              :node="node"
              :include-archived="includeArchived"
              @add-child="openCreate"
              @edit="openEdit"
              @move="openMove"
              @archive="archive"
              @restore="restore"
            />
          </ul>
        </div>
      </div>
    </div>

    <!-- Edit / Create modal -->
    <Teleport to="body">
    <div v-if="modal.open" class="modal-overlay" @click.self="closeModal">
      <div class="modal-card card border-0 shadow-lg rounded-4">
        <div class="card-body p-4">
          <h5 class="fw-bold mb-3">
            {{ modal.mode === 'create' ? 'Add account' : 'Edit account' }}
          </h5>
          <div v-if="modal.parentName" class="small text-muted mb-3">
            Under: <strong>{{ modal.parentName }}</strong>
          </div>

          <!-- Inline error — visible even when this modal is open -->
          <div v-if="modal.error" class="alert alert-danger py-2 small mb-3">
            <i class="fas fa-exclamation-triangle me-1"></i>{{ modal.error }}
          </div>

          <div class="mb-3">
            <label class="form-label small fw-bold">Name</label>
            <input v-model="form.name" type="text" class="form-control" placeholder="Account name" />
          </div>

          <div class="row g-3">
            <div class="col-md-6">
              <label class="form-label small fw-bold">Type</label>
              <select v-model="form.type" class="form-select">
                <option value="REVENUE">REVENUE</option>
                <option value="EXPENSE">EXPENSE</option>
                <option value="ASSET">ASSET</option>
                <option value="LIABILITY">LIABILITY</option>
                <option value="EQUITY">EQUITY</option>
              </select>
            </div>
            <div class="col-md-6">
              <label class="form-label small fw-bold">Default flow</label>
              <select v-model="form.default_flow" class="form-select">
                <option value="INCOME">INCOME</option>
                <option value="EXPENSE">EXPENSE</option>
              </select>
            </div>
          </div>

          <div class="mt-3">
            <label class="form-label small fw-bold">Description <span class="text-muted fw-normal">(optional)</span></label>
            <textarea v-model="form.description" class="form-control" rows="2"></textarea>
          </div>

          <div class="d-flex justify-content-end gap-2 mt-4">
            <button class="btn btn-outline-secondary" @click="closeModal" :disabled="saving">Cancel</button>
            <button class="btn btn-primary" @click="save" :disabled="saving || !form.name.trim()">
              <i class="fas fa-save me-1"></i>
              {{ saving ? 'Saving…' : 'Save' }}
            </button>
          </div>
        </div>
      </div>
    </div>
    </Teleport>

    <!-- Move modal -->
    <Teleport to="body">
    <div v-if="moveModal.open" class="modal-overlay" @click.self="closeMoveModal">
      <div class="modal-card card border-0 shadow-lg rounded-4">
        <div class="card-body p-4">
          <h5 class="fw-bold mb-3">Move account</h5>
          <div class="small text-muted mb-3">
            Moving: <strong>{{ moveModal.node?.name }}</strong>
          </div>

          <div v-if="moveModal.error" class="alert alert-danger py-2 small mb-3">
            <i class="fas fa-exclamation-triangle me-1"></i>{{ moveModal.error }}
          </div>

          <label class="form-label small fw-bold">New parent</label>
          <select v-model="moveModal.targetParentId" class="form-select">
            <option :value="null">— Root (no parent) —</option>
            <option v-for="cand in moveCandidates" :key="cand.id" :value="cand.id">
              {{ cand.indent }}{{ cand.name }}
            </option>
          </select>

          <div class="small text-muted mt-2">
            <i class="fas fa-info-circle me-1"></i>
            The account being moved and its descendants are excluded to prevent cycles.
          </div>

          <div class="d-flex justify-content-end gap-2 mt-4">
            <button class="btn btn-outline-secondary" @click="closeMoveModal" :disabled="moving">Cancel</button>
            <button class="btn btn-primary" @click="confirmMove" :disabled="moving">
              <i class="fas fa-arrow-right me-1"></i>
              {{ moving ? 'Moving…' : 'Move' }}
            </button>
          </div>
        </div>
      </div>
    </div>
    </Teleport>

    <!-- Notice modal (for archive/restore/global errors outside an open modal) -->
    <BaseModal
      v-model="notice.open"
      :modalTitle="notice.title"
      :footerClose="true"
    >
      <div class="d-flex align-items-start gap-3 py-2">
        <div class="icon-circle flex-shrink-0" :class="noticeIconBg">
          <i class="fas" :class="noticeIcon"></i>
        </div>
        <div class="pt-1" style="white-space: pre-wrap;">{{ notice.message }}</div>
      </div>
    </BaseModal>

    <!-- Confirm modal -->
    <ConfirmModal
      v-model="confirmState.open"
      :title="confirmState.title"
      :message="confirmState.message"
      :confirmText="confirmState.confirmText"
      :cancelText="confirmState.cancelText"
      :variant="confirmState.variant"
      @confirm="onConfirmAccept"
      @cancel="onConfirmReject"
    />
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue';
import axios from 'axios';
import BaseModal from '@/Components/Core/BaseModal.vue';
import ConfirmModal from '@/Components/Core/ConfirmModal.vue';
import { useAuth } from '@/composables/Core/useAuth';

const { isUltimate, isSuperOperator, isOperator } = useAuth();
const isBig3 = computed(() => isUltimate.value || isSuperOperator.value || isOperator.value);

// Recursive node component
const AccountNode = {
  name: 'AccountNode',
  props: { node: Object, includeArchived: Boolean },
  emits: ['add-child', 'edit', 'move', 'archive', 'restore'],
  setup(props, { emit }) {
    const expanded = ref(true);
    const children = computed(() => {
      const list = props.node.children || [];
      return props.includeArchived ? list : list.filter(c => c.is_active);
    });
    const hasChildren = computed(() => children.value.length > 0);
    return { expanded, children, hasChildren };
  },
  template: `
    <li class="account-node mb-1">
      <div class="d-flex align-items-center gap-2 py-2 px-2 rounded hover-bg" :class="{ 'opacity-50': !node.is_active }">
        <button class="btn btn-sm btn-link p-0 toggle-btn" v-if="hasChildren" @click="expanded = !expanded">
          <i class="fas" :class="expanded ? 'fa-chevron-down' : 'fa-chevron-right'"></i>
        </button>
        <span v-else class="toggle-spacer"></span>

        <span class="badge" :class="node.default_flow === 'INCOME' ? 'bg-success-subtle text-success' : 'bg-danger-subtle text-danger'">
          {{ node.default_flow || node.type }}
        </span>
        <span class="fw-semibold">{{ node.name }}</span>
        <span v-if="node.theme_key" class="badge bg-light text-muted small" :title="'theme: ' + node.theme_key">
          <i class="fas fa-palette"></i>
        </span>
        <span v-if="!node.is_active" class="badge bg-secondary small">archived</span>

        <div class="ms-auto d-flex gap-1">
          <button class="btn btn-sm btn-outline-primary" @click="$emit('add-child', node)" title="Add child">
            <i class="fas fa-plus"></i>
          </button>
          <button class="btn btn-sm btn-outline-secondary" @click="$emit('edit', node)" title="Edit">
            <i class="fas fa-pen"></i>
          </button>
          <button class="btn btn-sm btn-outline-secondary" @click="$emit('move', node)" title="Move">
            <i class="fas fa-arrows-up-down-left-right"></i>
          </button>
          <button v-if="node.is_active" class="btn btn-sm btn-outline-danger" @click="$emit('archive', node)" title="Archive">
            <i class="fas fa-archive"></i>
          </button>
          <button v-else class="btn btn-sm btn-outline-success" @click="$emit('restore', node)" title="Restore">
            <i class="fas fa-undo"></i>
          </button>
        </div>
      </div>

      <ul v-if="hasChildren && expanded" class="list-unstyled ms-4 ps-3 border-start">
        <account-node
          v-for="child in children"
          :key="child.id"
          :node="child"
          :include-archived="includeArchived"
          @add-child="(n) => $emit('add-child', n)"
          @edit="(n) => $emit('edit', n)"
          @move="(n) => $emit('move', n)"
          @archive="(n) => $emit('archive', n)"
          @restore="(n) => $emit('restore', n)"
        />
      </ul>
    </li>
  `,
};

const tree          = ref([]);
const loading       = ref(false);
const includeArchived = ref(false);
const saving        = ref(false);

// Store selector (store-level users only)
const stores          = ref([]);
const selectedStoreId = ref(null);

// Theme management (Big 3 only)
const themeOpen      = ref(false);
const themeInfo      = ref(null);
const themeDrift     = ref(null);
const loadingThemes  = ref(false);
const selectThemeKey = ref(null);
const switchingTheme = ref(false);
const applyingTheme  = ref(false);

const modal = ref({ open: false, mode: 'create', parentName: null, error: null });
const form  = ref(emptyForm());
const moveModal = ref({ open: false, node: null, targetParentId: null, error: null });
const moving    = ref(false);

// Notice (for errors that happen outside an open modal: archive, restore)
const notice = ref({ open: false, variant: 'info', title: 'Notice', message: '' });
const noticeIcon = computed(() => {
  if (notice.value.variant === 'danger')  return 'fa-exclamation-triangle text-danger';
  if (notice.value.variant === 'warning') return 'fa-exclamation-circle text-warning';
  if (notice.value.variant === 'success') return 'fa-check-circle text-success';
  return 'fa-info-circle text-primary';
});
const noticeIconBg = computed(() => {
  if (notice.value.variant === 'danger')  return 'bg-soft-danger';
  if (notice.value.variant === 'warning') return 'bg-soft-warning';
  if (notice.value.variant === 'success') return 'bg-soft-success';
  return 'bg-soft-primary';
});
function showNotice(message, { variant = 'info', title } = {}) {
  notice.value = {
    open: true, variant,
    title: title ?? (variant === 'danger' ? 'Error' : variant === 'success' ? 'Success' : 'Notice'),
    message: String(message ?? ''),
  };
}

// Confirm modal
const confirmState = ref({ open: false, title: 'Confirm Action', message: '', confirmText: 'Confirm', cancelText: 'Cancel', variant: 'info' });
let confirmResolver = null;
function askConfirm(message, opts = {}) {
  confirmState.value = { open: true, title: opts.title ?? 'Confirm Action', message, confirmText: opts.confirmText ?? 'Confirm', cancelText: opts.cancelText ?? 'Cancel', variant: opts.variant ?? 'info' };
  return new Promise((resolve) => { confirmResolver = resolve; });
}
function onConfirmAccept() { if (confirmResolver) { confirmResolver(true);  confirmResolver = null; } }
function onConfirmReject() { if (confirmResolver) { confirmResolver(false); confirmResolver = null; } }

const moveCandidates = computed(() => {
  if (!moveModal.value.node) return [];
  const excludeId = moveModal.value.node.id;
  const list = [];
  const walk = (nodes, depth) => {
    for (const n of nodes) {
      if (n.id === excludeId) continue;
      if (!n.is_active) continue;
      list.push({ id: n.id, name: n.name, indent: '  '.repeat(depth) });
      if (n.children?.length) walk(n.children, depth + 1);
    }
  };
  walk(tree.value, 0);
  return list;
});

function emptyForm() {
  return { id: null, parent_id: null, name: '', type: 'REVENUE', default_flow: 'INCOME', description: '' };
}

const visibleTree = computed(() =>
  includeArchived.value ? tree.value : tree.value.filter(n => n.is_active)
);

onMounted(async () => {
  if (!isBig3.value) {
    await fetchStores();
  } else {
    loadThemes();
  }
  fetchAll();
});

async function loadThemes() {
  loadingThemes.value = true;
  try {
    const [infoRes, driftRes] = await Promise.all([
      axios.post('/admin/accounting/theme', {}),
      axios.post('/admin/accounting/theme/drift', {}),
    ]);
    themeInfo.value  = infoRes.data ?? null;
    themeDrift.value = driftRes.data?.data ?? null;
    if (themeInfo.value?.current && !selectThemeKey.value) {
      selectThemeKey.value = themeInfo.value.current;
    }
  } catch (e) {
    console.error('Failed to load themes', e);
  } finally {
    loadingThemes.value = false;
  }
}

async function switchTheme() {
  if (!selectThemeKey.value || selectThemeKey.value === themeInfo.value?.current) return;
  switchingTheme.value = true;
  try {
    const res = await axios.post('/admin/accounting/theme/set', { key: selectThemeKey.value });
    if (res.data?.success) {
      await loadThemes();
      await fetchAll();
      await reapplyTheme();
    } else {
      showNotice(res.data?.message || 'Could not switch theme.', { variant: 'danger' });
    }
  } catch (e) {
    showNotice(e.response?.data?.message || 'Could not switch theme.', { variant: 'danger' });
  } finally {
    switchingTheme.value = false;
  }
}

async function reapplyTheme() {
  applyingTheme.value = true;
  try {
    const res = await axios.post('/admin/accounting/theme/apply', {});
    if (res.data?.success) {
      showNotice(res.data.message || 'Theme applied.', { variant: 'success', title: 'Theme Applied' });
      await loadThemes();
      await fetchAll();
    } else {
      showNotice(res.data?.message || 'Apply failed.', { variant: 'danger' });
    }
  } catch (e) {
    showNotice(e.response?.data?.message || 'Apply failed.', { variant: 'danger' });
  } finally {
    applyingTheme.value = false;
  }
}

async function fetchStores() {
  try {
    const res = await axios.post('/Admin/Stores/Selectable', {});
    stores.value = res.data?.data ?? [];
    if (stores.value.length > 0) {
      selectedStoreId.value = stores.value[0].id ?? null;
    }
  } catch (e) {
    console.error('Failed to load stores', e);
  }
}

function selectStore(s) {
  selectedStoreId.value = s.id ?? null;
  fetchAll();
}

async function fetchAll() {
  loading.value = true;
  try {
    const treeRes = await axios.post('/admin/accounting/tree', {});
    tree.value = treeRes.data?.data ?? [];
  } catch (e) {
    console.error('Failed to load accounts', e);
  } finally {
    loading.value = false;
  }
}

function openCreate(parentNode) {
  form.value = emptyForm();
  if (parentNode) {
    form.value.parent_id    = parentNode.id;
    form.value.type         = parentNode.type || 'REVENUE';
    form.value.default_flow = parentNode.default_flow || 'INCOME';
  }
  modal.value = { open: true, mode: 'create', parentName: parentNode?.name ?? null, error: null };
}

function openEdit(node) {
  form.value = {
    id:           node.id,
    parent_id:    node.parent_id,
    name:         node.name,
    type:         node.type,
    default_flow: node.default_flow || 'INCOME',
    description:  node.description || '',
  };
  modal.value = { open: true, mode: 'edit', parentName: null, error: null };
}

function closeModal() {
  if (saving.value) return;
  modal.value.open = false;
}

async function save() {
  saving.value   = true;
  modal.value.error = null;
  try {
    const url = modal.value.mode === 'create'
      ? '/admin/accounting/accounts/create'
      : '/admin/accounting/accounts/update';
    const res = await axios.post(url, form.value);
    if (!res.data?.success) {
      modal.value.error = res.data?.message || 'Save failed.';
      return;
    }
    modal.value.open = false;
    await fetchAll();
  } catch (e) {
    // Show error inline so it's visible even while this modal is open
    modal.value.error = e.response?.data?.message || 'Save failed. Please try again.';
  } finally {
    saving.value = false;
  }
}

function openMove(node) {
  moveModal.value = { open: true, node, targetParentId: node.parent_id ?? null, error: null };
}

function closeMoveModal() {
  if (moving.value) return;
  moveModal.value.open = false;
}

async function confirmMove() {
  if (!moveModal.value.node) return;
  moving.value        = true;
  moveModal.value.error = null;
  try {
    const res = await axios.post('/admin/accounting/accounts/move', {
      id:        moveModal.value.node.id,
      parent_id: moveModal.value.targetParentId,
    });
    if (!res.data?.success) {
      moveModal.value.error = res.data?.message || 'Move failed.';
      return;
    }
    moveModal.value.open = false;
    await fetchAll();
  } catch (e) {
    moveModal.value.error = e.response?.data?.message || 'Move failed.';
  } finally {
    moving.value = false;
  }
}

async function archive(node) {
  const ok = await askConfirm(
    `Archive "${node.name}"? It will be hidden from new transactions.`,
    { title: 'Archive account', confirmText: 'Archive', variant: 'danger' }
  );
  if (!ok) return;
  try {
    const res = await axios.post('/admin/accounting/accounts/archive', { id: node.id });
    if (!res.data?.success) { showNotice(res.data?.message || 'Archive failed.', { variant: 'danger' }); return; }
    await fetchAll();
  } catch (e) {
    showNotice(e.response?.data?.message || 'Archive failed.', { variant: 'danger' });
  }
}

async function restore(node) {
  try {
    const res = await axios.post('/admin/accounting/accounts/restore', { id: node.id });
    if (!res.data?.success) { showNotice(res.data?.message || 'Restore failed.', { variant: 'danger' }); return; }
    await fetchAll();
  } catch (e) {
    showNotice(e.response?.data?.message || 'Restore failed.', { variant: 'danger' });
  }
}
</script>

<style scoped>
.bg-primary-gradient { background: linear-gradient(135deg, #0d6efd 0%, #0a58ca 100%); }
.toggle-btn { width: 1.5rem; }
.toggle-spacer { display: inline-block; width: 1.5rem; }
.hover-bg:hover { background-color: rgba(13, 110, 253, 0.06); }
.account-node ul { margin-top: .25rem; }

.modal-overlay {
  position: fixed; inset: 0;
  background: rgba(0,0,0,.45);
  z-index: 1080;
  display: flex; align-items: center; justify-content: center;
  padding: 1rem;
}
.modal-card { width: 100%; max-width: 520px; background: #fff; }
.ls-wide { letter-spacing: .08em; }

.icon-circle {
  width: 44px; height: 44px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
}
.bg-soft-danger  { background-color: rgba(231, 76, 60, 0.12); }
.bg-soft-warning { background-color: rgba(243, 156, 18, 0.12); }
.bg-soft-success { background-color: rgba(46, 204, 113, 0.12); }
.bg-soft-primary { background-color: rgba(52, 152, 219, 0.12); }
</style>
