<template>
  <fluent-design-system-provider accent-base-color="#2457a6" :base-layer-luminance="fluentLuminance">
    <v-app :theme="activeTheme">
      <LoginView v-if="!token" :error="error" :form="loginForm" :loading="loading" @login="login" />

      <div v-else class="app-shell">
        <v-navigation-drawer class="rail" width="254" permanent>
          <div class="brand-lockup">
            <span class="brand-mark">MA</span>
            <span class="brand-name">MixedAssets</span>
          </div>
          <v-divider />
          <v-list nav density="compact" class="pa-3">
            <v-list-item
              v-for="item in visibleNavItems"
              :key="item.key"
              :active="activeView === item.key"
              :prepend-icon="item.icon"
              :title="item.label"
              rounded="sm"
              @click="activeView = item.key"
            />
          </v-list>
          <template #append>
            <div class="pa-4">
              <div class="text-body-2 font-weight-bold">{{ user?.name }}</div>
              <div class="text-caption quiet">{{ user?.role }}</div>
              <v-btn class="mt-3" block variant="tonal" prepend-icon="mdi-logout" @click="logout">Sign out</v-btn>
            </div>
          </template>
        </v-navigation-drawer>

        <TopNav
          :preferences="profilePreferences"
          :saving="preferenceSaving"
          :subtitle="currentSubtitle"
          :theme-items="themeItems"
          :title="currentTitle"
          :user="user"
          @logout="logout"
          @save-preferences="saveProfilePreferences"
        >
          <template #actions>
              <v-btn v-if="activeView === 'assets' && canEditAssets" color="primary" prepend-icon="mdi-plus" @click="newAsset">New asset</v-btn>
              <v-btn v-if="activeView === 'reports'" color="secondary" prepend-icon="mdi-file-pdf-box" @click="downloadPdf">PDF</v-btn>
          </template>
        </TopNav>

        <v-main>
          <DashboardView
            v-if="activeView === 'dashboard'"
            :category-chart="categoryChart"
            :chart-options="chartOptions"
            :currency="currency"
            :dashboard="dashboard"
            :short-date="shortDate"
          />
          <AssetsView
            v-if="activeView === 'assets'"
            :all-selected="allSelected"
            :assets="assets"
            :asset-filters="assetFilters"
            :currency="currency"
            :selected-asset-ids="selectedAssetIds"
            :status-items="statusItems"
            @edit-asset="editAsset"
            @export-assets="exportAssets"
            @filter-assets="filterAssets"
            @import-assets="importAssets"
            @open-mass-edit="massDialog = true"
            @toggle-all="toggleAll"
            @toggle-asset="toggleAsset"
          />
          <AssignmentsView
            v-if="activeView === 'assignments'"
            :assignments="assignments"
            :assets="assets"
            :assignment-saving="assignmentSaving"
            :employees="employees"
            :short-date="shortDate"
            :summary="assignmentSummary"
            @add-employee="addEmployee"
            @assign-asset="assignAsset"
            @release-assignment="releaseAssignment"
            @reload="loadAssignments"
          />
          <ReportsView
            v-if="activeView === 'reports'"
            :book-items="bookItems"
            :chart-options="chartOptions"
            :currency="currency"
            :depreciation-report="depreciationReport"
            :monthly-chart="monthlyChart"
            :report-filters="reportFilters"
            @filter-reports="filterReports"
          />
          <TemplatesView
            v-if="activeView === 'templates'"
            :category-items="categoryItems"
            :custom-field-types="customFieldTypes"
            :method-items="methodItems"
            :template-form="templateForm"
            :templates="templates"
            @save-template="saveTemplate"
          />
          <AdminView
            v-if="activeView === 'admin'"
            :role-capabilities="roleCapabilities"
            :role-permissions="rolePermissions"
            :roles="roles"
            :short-date="shortDate"
            :settings="settings"
            :tax-rules="taxRules"
            :team-saving="teamSaving"
            :teams="teams"
            :user-saving="userSaving"
            :users="users"
            :workday-connection="workdayConnection"
            :workday-saving="workdaySaving"
            :workday-syncing="workdaySyncing"
            @create-team="createTeam"
            @create-user="createUser"
            @save-settings="saveSettings"
            @save-workday="saveWorkdayConnection"
            @sync-workday="syncWorkday"
            @update-user="updateUser"
          />
        </v-main>

        <AssetDrawer
          v-model="assetDrawer"
          :asset-form="assetForm"
          :category-items="categoryItems"
          :drawer-error="drawerError"
          :entity-options="entityOptions"
          :method-items="methodItems"
          :saving="saving"
          :selected-template-fields="selectedTemplateFields"
          :selected-template-id="selectedTemplateId"
          :status-items="statusItems"
          :template-options="templateOptions"
          @save-asset="saveAsset"
          @select-template="applyTemplate"
        />

        <MassEditDialog
          v-model="massDialog"
          :changes="massChanges"
          :status-items="statusItems"
          @apply="massUpdate"
        />
      </div>
    </v-app>
  </fluent-design-system-provider>
</template>

<script>
import AdminView from './views/AdminView.vue';
import AssignmentsView from './views/AssignmentsView.vue';
import AssetsView from './views/AssetsView.vue';
import DashboardView from './views/DashboardView.vue';
import LoginView from './views/LoginView.vue';
import ReportsView from './views/ReportsView.vue';
import TemplatesView from './views/TemplatesView.vue';
import AssetDrawer from './components/AssetDrawer.vue';
import MassEditDialog from './components/MassEditDialog.vue';
import TopNav from './components/TopNav.vue';
import { apiRequest, loginRequest, saveBlob } from './services/api';
import { blankAsset, defaultValueForField, normalizeCustomFields } from './utils/assets';
import { currency, shortDate } from './utils/format';
import { bookItems, customFieldTypes, navItems, statusItems, themeItems } from './constants';

const emptyStats = {
  asset_count: 0,
  total_cost: 0,
  disposed_count: 0,
  in_service_count: 0
};

export default {
  components: {
    AdminView,
    AssignmentsView,
    AssetDrawer,
    AssetsView,
    DashboardView,
    LoginView,
    MassEditDialog,
    ReportsView,
    TemplatesView,
    TopNav
  },
  data() {
    return {
      activeView: 'dashboard',
      assets: [],
      assetDrawer: false,
      assetFilters: { search: '', status: null },
      assetForm: blankAsset(),
      assignments: [],
      assignmentSaving: false,
      assignmentSummary: {},
      bookItems,
      chartOptions: {
        responsive: true,
        maintainAspectRatio: false,
        plugins: { legend: { display: false } },
        scales: { y: { beginAtZero: true, ticks: { callback: (value) => `$${Number(value).toLocaleString()}` } } }
      },
      customFieldTypes,
      dashboard: { stats: { ...emptyStats }, byCategory: [], byStatus: [], upcomingTasks: [], auditTrail: [] },
      depreciationReport: { totals: { depreciation: 0 }, rows: [] },
      drawerError: '',
      employees: [],
      entities: [],
      error: '',
      loading: false,
      loginForm: { email: 'admin@mixedassets.local', password: 'ChangeMe123!' },
      massChanges: { status: null, location: '', department: '' },
      massDialog: false,
      monthlyReport: { months: [] },
      navItems,
      preferenceSaving: false,
      profilePreferences: { theme: localStorage.getItem('mixedassets.theme') || 'mixedAssetsDark' },
      references: [],
      reportFilters: { book: 'GAAP', year: new Date().getFullYear() },
      roleCapabilities: [],
      rolePermissions: {},
      roles: [],
      saving: false,
      selectedAssetIds: [],
      selectedTemplateId: null,
      settings: {},
      statusItems,
      taxRules: [],
      teamSaving: false,
      teams: [],
      templateForm: {
        name: '',
        description: '',
        defaults: { category: 'Computer Equipment', useful_life_months: 60, depreciation_method: 'straight_line' },
        custom_fields: []
      },
      templates: [],
      themeItems,
      token: localStorage.getItem('mixedassets.token') || '',
      user: JSON.parse(localStorage.getItem('mixedassets.user') || 'null'),
      userSaving: false,
      users: [],
      workdayConnection: {},
      workdaySaving: false,
      workdaySyncing: false
    };
  },
  computed: {
    allSelected() {
      return this.assets.length > 0 && this.selectedAssetIds.length === this.assets.length;
    },
    categoryChart() {
      return {
        labels: this.dashboard.byCategory.map((row) => row.category),
        datasets: [{ data: this.dashboard.byCategory.map((row) => row.value), backgroundColor: '#2457a6' }]
      };
    },
    categoryItems() {
      const fromRefs = this.references.filter((item) => item.type === 'category').map((item) => item.name);
      return [...new Set([...fromRefs, 'Computer Equipment', 'Office Furniture', 'Vehicles', 'Leasehold Improvements', 'Uncategorized'])];
    },
    canEditAssets() {
      return ['admin', 'finance', 'operations'].includes(this.user?.role);
    },
    currentSubtitle() {
      return {
        dashboard: 'Portfolio value, lifecycle activity, and open work',
        assets: 'Asset register, imports, exports, and lifecycle updates',
        assignments: 'Assign assets to people, departments, and locations with full custody history',
        reports: 'Depreciation schedules, monthly expense, and book values',
        templates: 'JSON-driven entry defaults and custom fields',
        admin: 'Users, database, CORS, and tax-rule configuration'
      }[this.activeView];
    },
    currentTitle() {
      return {
        dashboard: 'Dashboard',
        assets: 'Asset register',
        assignments: 'Assignments',
        reports: 'Reports',
        templates: 'Templates',
        admin: 'Configuration'
      }[this.activeView];
    },
    entityOptions() {
      return this.entities.map((entity) => ({ title: entity.name, value: entity.id }));
    },
    activeTheme() {
      return this.profilePreferences.theme || 'mixedAssetsDark';
    },
    fluentLuminance() {
      return this.activeTheme === 'mixedAssetsDark' ? '0.12' : '1';
    },
    methodItems() {
      const methods = this.taxRules[0]?.rules_json?.methods || [];
      const fallback = [
        { code: 'straight_line', family: 'GAAP', label: 'Straight-line' },
        { code: 'sum_of_years_digits', family: 'GAAP', label: 'Sum-of-years-digits' },
        { code: 'declining_balance_200', family: 'GAAP', label: '200% declining balance' },
        { code: 'manual', family: 'Manual', label: 'Manual depreciation entry' }
      ];
      return (methods.length ? methods : fallback).map((method) => ({
        title: `${method.family} · ${method.label}`,
        value: method.code
      }));
    },
    monthlyChart() {
      return {
        labels: this.monthlyReport.months.map((row) => `M${row.month}`),
        datasets: [{ data: this.monthlyReport.months.map((row) => row.depreciation), backgroundColor: '#006c6a' }]
      };
    },
    selectedTemplate() {
      return this.templates.find((template) => template.id === this.selectedTemplateId) || null;
    },
    selectedTemplateFields() {
      return normalizeCustomFields(this.selectedTemplate?.custom_fields || []);
    },
    templateOptions() {
      return this.templates.map((template) => ({ title: template.name, value: template.id }));
    },
    visibleNavItems() {
      const allowedByRole = {
        admin: ['dashboard', 'assets', 'assignments', 'reports', 'templates', 'admin'],
        finance: ['dashboard', 'assets', 'assignments', 'reports', 'templates'],
        operations: ['dashboard', 'assets', 'assignments'],
        viewer: ['dashboard', 'assets', 'assignments', 'reports', 'templates']
      };
      const allowed = allowedByRole[this.user?.role] || allowedByRole.viewer;
      return this.navItems.filter((item) => allowed.includes(item.key));
    }
  },
  watch: {
    activeView(view) {
      if (view === 'reports') this.loadReports();
      if (view === 'admin') this.loadAdmin();
      if (view === 'assignments') this.loadAssignments();
    },
    visibleNavItems(items) {
      if (!items.some((item) => item.key === this.activeView)) {
        this.activeView = items[0]?.key || 'dashboard';
      }
    }
  },
  mounted() {
    if (this.token) this.loadInitial();
  },
  methods: {
    currency,
    shortDate,
    async api(path, options = {}) {
      return apiRequest(path, this.token, options);
    },
    async addEmployee(employee) {
      await this.api('/api/employees', { method: 'POST', body: JSON.stringify(employee) });
      await this.loadAssignments();
    },
    applyTemplate(id) {
      this.selectedTemplateId = id || null;
      const template = this.templates.find((item) => item.id === id);
      if (!template) {
        this.assetForm = { ...this.assetForm, template_id: null };
        return;
      }
      const customFields = { ...(this.assetForm.custom_fields || {}) };
      for (const field of normalizeCustomFields(template.custom_fields)) {
        if (customFields[field.key] === undefined) customFields[field.key] = defaultValueForField(field);
      }
      this.assetForm = { ...this.assetForm, ...template.defaults, custom_fields: customFields, template_id: template.id };
    },
    async assignAsset(form) {
      this.assignmentSaving = true;
      try {
        await this.api('/api/assignments', { method: 'POST', body: JSON.stringify(form) });
        await Promise.all([this.loadAssignments(), this.loadAssets(), this.loadDashboard()]);
      } finally {
        this.assignmentSaving = false;
      }
    },
    async createTeam(team) {
      this.teamSaving = true;
      try {
        await this.api('/api/teams', { method: 'POST', body: JSON.stringify(team) });
        await this.loadAdmin();
      } finally {
        this.teamSaving = false;
      }
    },
    async createUser(user) {
      this.userSaving = true;
      try {
        await this.api('/api/users', { method: 'POST', body: JSON.stringify(user) });
        await this.loadAdmin();
      } finally {
        this.userSaving = false;
      }
    },
    async downloadPdf() {
      const blob = await (await this.api(`/api/reports/depreciation.pdf?year=${this.reportFilters.year}&book=${this.reportFilters.book}`)).blob();
      saveBlob(blob, `mixedassets-${this.reportFilters.book}-${this.reportFilters.year}.pdf`);
    },
    editAsset(asset) {
      this.assetForm = { ...blankAsset(), ...asset, custom_fields: asset.custom_fields || {} };
      this.selectedTemplateId = asset.template_id || null;
      this.assetDrawer = true;
    },
    async exportAssets(format) {
      const blob = await (await this.api(`/api/export/assets?format=${format}`)).blob();
      saveBlob(blob, `mixedassets-assets.${format}`);
    },
    filterAssets(filters) {
      this.assetFilters = filters;
      this.loadAssets();
    },
    filterReports(filters) {
      this.reportFilters = filters;
      this.loadReports();
    },
    async importAssets(event) {
      const [file] = event.target.files || [];
      if (!file) return;
      const formData = new FormData();
      formData.append('file', file);
      await this.api('/api/import/assets', { method: 'POST', body: formData });
      event.target.value = '';
      await this.loadAssets();
      await this.loadDashboard();
    },
    async loadAdmin() {
      const [settings, rules, workday, users, teams, accessControl] = await Promise.all([
        this.api('/api/settings').then((r) => r.json()).catch(() => ({ settings: {} })),
        this.api('/api/tax-rules').then((r) => r.json()),
        this.api('/api/workday/connection').then((r) => r.json()).catch(() => ({ connection: {} })),
        this.api('/api/users').then((r) => r.json()).catch(() => ({ users: [] })),
        this.api('/api/teams').then((r) => r.json()).catch(() => ({ teams: [] })),
        this.api('/api/access-control').then((r) => r.json()).catch(() => ({
          roles: [],
          rolePermissions: {},
          roleCapabilities: []
        }))
      ]);
      this.settings = settings.settings;
      this.taxRules = rules.ruleSets;
      this.workdayConnection = workday.connection || {};
      this.users = users.users || [];
      this.teams = teams.teams || [];
      this.roles = accessControl.roles || [];
      this.rolePermissions = accessControl.rolePermissions || {};
      this.roleCapabilities = accessControl.roleCapabilities || [];
    },
    async loadAssets() {
      const params = new URLSearchParams();
      if (this.assetFilters.search) params.set('search', this.assetFilters.search);
      if (this.assetFilters.status) params.set('status', this.assetFilters.status);
      const data = await (await this.api(`/api/assets?${params.toString()}`)).json();
      this.assets = data.assets;
      this.selectedAssetIds = this.selectedAssetIds.filter((id) => this.assets.some((asset) => asset.id === id));
    },
    async loadDashboard() {
      this.dashboard = await (await this.api('/api/dashboard')).json();
    },
    async loadInitial() {
      await Promise.all([
        this.loadProfile(),
        this.loadDashboard(),
        this.loadAssets(),
        this.loadAssignments(),
        this.api('/api/entities').then((r) => r.json()).then((data) => { this.entities = data.entities; }),
        this.api('/api/references').then((r) => r.json()).then((data) => { this.references = data.references; }),
        this.api('/api/templates').then((r) => r.json()).then((data) => { this.templates = data.templates; }),
        this.api('/api/tax-rules').then((r) => r.json()).then((data) => { this.taxRules = data.ruleSets; })
      ]);
    },
    async loadAssignments() {
      const [employees, assignments, workday] = await Promise.all([
        this.api('/api/employees').then((r) => r.json()),
        this.api('/api/assignments').then((r) => r.json()),
        this.api('/api/workday/connection').then((r) => r.json()).catch(() => ({ connection: {} }))
      ]);
      this.employees = employees.employees;
      this.assignments = assignments.assignments;
      this.assignmentSummary = assignments.summary;
      this.workdayConnection = workday.connection || {};
    },
    async loadProfile() {
      const profile = await (await this.api('/api/profile')).json();
      this.user = profile.user;
      this.profilePreferences = { theme: 'mixedAssetsDark', ...(profile.preferences || {}) };
      localStorage.setItem('mixedassets.user', JSON.stringify(profile.user));
      localStorage.setItem('mixedassets.theme', this.activeTheme);
    },
    async loadReports() {
      const query = `year=${this.reportFilters.year}&book=${this.reportFilters.book}`;
      const [annual, monthly] = await Promise.all([
        this.api(`/api/reports/depreciation?${query}`).then((r) => r.json()),
        this.api(`/api/reports/monthly-depreciation?${query}`).then((r) => r.json())
      ]);
      this.depreciationReport = annual;
      this.monthlyReport = monthly;
    },
    async login(form) {
      this.loading = true;
      this.error = '';
      try {
        const data = await loginRequest(form);
        this.loginForm = { ...form };
        this.token = data.token;
        this.user = data.user;
        localStorage.setItem('mixedassets.token', data.token);
        localStorage.setItem('mixedassets.user', JSON.stringify(data.user));
        await this.loadInitial();
      } catch (error) {
        this.error = error.message;
      } finally {
        this.loading = false;
      }
    },
    logout() {
      this.token = '';
      this.user = null;
      localStorage.removeItem('mixedassets.token');
      localStorage.removeItem('mixedassets.user');
    },
    async massUpdate(changesInput) {
      const changes = Object.fromEntries(Object.entries(changesInput).filter(([, value]) => value !== '' && value !== null));
      await this.api('/api/assets/mass-update', { method: 'POST', body: JSON.stringify({ ids: this.selectedAssetIds, changes }) });
      this.massDialog = false;
      this.massChanges = { status: null, location: '', department: '' };
      await this.loadAssets();
      await this.loadDashboard();
    },
    newAsset() {
      this.assetForm = blankAsset();
      this.assetForm.entity_id = this.entities[0]?.id || null;
      this.selectedTemplateId = null;
      this.drawerError = '';
      this.assetDrawer = true;
    },
    async saveAsset(assetInput) {
      this.saving = true;
      this.drawerError = '';
      try {
        const payload = {
          ...assetInput,
          books: this.bookItems.map((book) => ({
            book_type: book,
            depreciation_method: assetInput.depreciation_method,
            useful_life_months: assetInput.useful_life_months,
            cost: assetInput.acquisition_cost
          }))
        };
        const method = assetInput.id ? 'PUT' : 'POST';
        const url = assetInput.id ? `/api/assets/${assetInput.id}` : '/api/assets';
        await this.api(url, { method, body: JSON.stringify(payload) });
        this.assetDrawer = false;
        await this.loadAssets();
        await this.loadDashboard();
      } catch (error) {
        this.drawerError = error.message;
      } finally {
        this.saving = false;
      }
    },
    async saveSettings(settings) {
      await this.api('/api/settings', { method: 'PUT', body: JSON.stringify({ settings }) });
      await this.loadAdmin();
    },
    async releaseAssignment(assignment) {
      await this.api(`/api/assignments/${assignment.id}/release`, {
        method: 'PUT',
        body: JSON.stringify({ release_reason: 'Released from UI' })
      });
      await Promise.all([this.loadAssignments(), this.loadAssets()]);
    },
    async saveProfilePreferences(preferences, options = { persist: true }) {
      this.profilePreferences = { ...this.profilePreferences, ...(preferences || {}) };
      localStorage.setItem('mixedassets.theme', this.activeTheme);
      if (!options.persist) return;

      this.preferenceSaving = true;
      try {
        const profile = await (await this.api('/api/profile', {
          method: 'PUT',
          body: JSON.stringify({ preferences: this.profilePreferences })
        })).json();
        this.user = profile.user;
        this.profilePreferences = { theme: 'mixedAssetsDark', ...(profile.preferences || {}) };
        localStorage.setItem('mixedassets.user', JSON.stringify(profile.user));
        localStorage.setItem('mixedassets.theme', this.activeTheme);
      } finally {
        this.preferenceSaving = false;
      }
    },
    async saveWorkdayConnection(connection) {
      this.workdaySaving = true;
      try {
        const body = { ...connection };
        if (!body.client_secret) delete body.client_secret;
        await this.api('/api/workday/connection', { method: 'PUT', body: JSON.stringify(body) });
        await this.loadAssignments();
      } finally {
        this.workdaySaving = false;
      }
    },
    async saveTemplate(form) {
      const payload = {
        ...form,
        custom_fields: normalizeCustomFields(form.custom_fields)
      };
      await this.api('/api/templates', { method: 'POST', body: JSON.stringify(payload) });
      const data = await (await this.api('/api/templates')).json();
      this.templates = data.templates;
      this.templateForm = {
        name: '',
        description: '',
        defaults: { category: 'Computer Equipment', useful_life_months: 60, depreciation_method: 'straight_line' },
        custom_fields: []
      };
    },
    async syncWorkday() {
      this.workdaySyncing = true;
      try {
        await this.api('/api/workday/sync-workers', { method: 'POST', body: JSON.stringify({}) });
        await this.loadAssignments();
      } finally {
        this.workdaySyncing = false;
      }
    },
    async updateUser(user) {
      this.userSaving = true;
      try {
        const body = { ...user };
        if (!body.password) delete body.password;
        await this.api(`/api/users/${user.id}`, { method: 'PUT', body: JSON.stringify(body) });
        await this.loadAdmin();
      } finally {
        this.userSaving = false;
      }
    },
    toggleAll(value) {
      this.selectedAssetIds = value ? this.assets.map((asset) => asset.id) : [];
    },
    toggleAsset(id) {
      this.selectedAssetIds = this.selectedAssetIds.includes(id)
        ? this.selectedAssetIds.filter((assetId) => assetId !== id)
        : [...this.selectedAssetIds, id];
    }
  }
};
</script>
