/**
 * DATATABLE LWC COMPONENT TEMPLATE
 *
 * This template demonstrates lightning-datatable with:
 * - Column configuration
 * - Row selection (single/multi)
 * - Inline editing
 * - Sorting
 * - Infinite scrolling
 * - Row actions
 *
 * Replace: datatableComponent → yourComponentName
 */

import { LightningElement, api, wire, track } from 'lwc';
import { refreshApex } from '@salesforce/apex';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { NavigationMixin } from 'lightning/navigation';
import getRecords from '@salesforce/apex/DatatableController.getRecords';
import updateRecords from '@salesforce/apex/DatatableController.updateRecords';
import deleteRecords from '@salesforce/apex/DatatableController.deleteRecords';

// Row actions
const actions = [
  { label: 'View', name: 'view' },
  { label: 'Edit', name: 'edit' },
  { label: 'Delete', name: 'delete' },
];

// Column definitions
const COLUMNS = [
  {
    label: 'Account Name',
    fieldName: 'nameUrl',
    type: 'url',
    typeAttributes: {
      label: { fieldName: 'Name' },
      target: '_blank',
    },
    sortable: true,
  },
  {
    label: 'Industry',
    fieldName: 'Industry',
    type: 'text',
    sortable: true,
    editable: true,
  },
  {
    label: 'Annual Revenue',
    fieldName: 'AnnualRevenue',
    type: 'currency',
    typeAttributes: {
      currencyCode: 'USD',
      minimumFractionDigits: 0,
    },
    sortable: true,
    editable: true,
    cellAttributes: { alignment: 'right' },
  },
  {
    label: 'Phone',
    fieldName: 'Phone',
    type: 'phone',
    editable: true,
  },
  {
    label: 'Created Date',
    fieldName: 'CreatedDate',
    type: 'date',
    typeAttributes: {
      year: 'numeric',
      month: 'short',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
    },
    sortable: true,
  },
  {
    label: 'Active',
    fieldName: 'IsActive__c',
    type: 'boolean',
    editable: true,
  },
  {
    type: 'action',
    typeAttributes: { rowActions: actions },
  },
];

export default class DatatableComponent extends NavigationMixin(LightningElement) {
  // ═══════════════════════════════════════════════════════════════════════
  // PUBLIC API
  // ═══════════════════════════════════════════════════════════════════════

  @api recordId;
  @api maxRows = 50;
  @api enableInfiniteScroll = false;
  @api showRowNumbers = false;

  // ═══════════════════════════════════════════════════════════════════════
  // PRIVATE PROPERTIES
  // ═══════════════════════════════════════════════════════════════════════

  columns = COLUMNS;
  @track data = [];
  error;
  isLoading = true;

  // Sorting
  sortBy;
  sortDirection = 'asc';

  // Selection
  selectedRows = [];
  draftValues = [];

  // Infinite scroll
  offset = 0;
  loadMoreStatus;
  totalRecords = 0;

  // Wire result for refresh
  wiredRecordsResult;

  // ═══════════════════════════════════════════════════════════════════════
  // WIRE SERVICE
  // ═══════════════════════════════════════════════════════════════════════

  @wire(getRecords, {
    parentId: '$recordId',
    limitSize: '$maxRows',
    offset: '$offset',
    sortBy: '$sortBy',
    sortDirection: '$sortDirection',
  })
  wiredRecords(result) {
    this.wiredRecordsResult = result;
    this.isLoading = false;

    const { data, error } = result;

    if (data) {
      // Add URL field for navigation
      this.data = data.records.map((record) => ({
        ...record,
        nameUrl: `/${record.Id}`,
      }));
      this.totalRecords = data.totalCount;
      this.error = undefined;
    } else if (error) {
      this.error = this.reduceErrors(error);
      this.data = [];
    }
  }

  // ═══════════════════════════════════════════════════════════════════════
  // GETTERS
  // ═══════════════════════════════════════════════════════════════════════

  get hasData() {
    return this.data && this.data.length > 0;
  }

  get hasSelection() {
    return this.selectedRows && this.selectedRows.length > 0;
  }

  get selectedCount() {
    return this.selectedRows.length;
  }

  get tableTitle() {
    return `Accounts (${this.totalRecords})`;
  }

  // ═══════════════════════════════════════════════════════════════════════
  // SORTING
  // ═══════════════════════════════════════════════════════════════════════

  handleSort(event) {
    this.sortBy = event.detail.fieldName;
    this.sortDirection = event.detail.sortDirection;
    this.isLoading = true;
    // Wire will automatically refetch with new sort params
  }

  // ═══════════════════════════════════════════════════════════════════════
  // SELECTION
  // ═══════════════════════════════════════════════════════════════════════

  handleRowSelection(event) {
    this.selectedRows = event.detail.selectedRows;

    // Dispatch event for parent
    this.dispatchEvent(
      new CustomEvent('selection', {
        detail: {
          selectedRows: this.selectedRows,
          selectedIds: this.selectedRows.map((row) => row.Id),
        },
      })
    );
  }

  // ═══════════════════════════════════════════════════════════════════════
  // ROW ACTIONS
  // ═══════════════════════════════════════════════════════════════════════

  handleRowAction(event) {
    const actionName = event.detail.action.name;
    const row = event.detail.row;

    switch (actionName) {
      case 'view':
        this.navigateToView(row.Id);
        break;
      case 'edit':
        this.navigateToEdit(row.Id);
        break;
      case 'delete':
        this.handleDeleteRow(row);
        break;
      default:
        break;
    }
  }

  navigateToView(recordId) {
    this[NavigationMixin.Navigate]({
      type: 'standard__recordPage',
      attributes: {
        recordId: recordId,
        objectApiName: 'Account',
        actionName: 'view',
      },
    });
  }

  navigateToEdit(recordId) {
    this[NavigationMixin.Navigate]({
      type: 'standard__recordPage',
      attributes: {
        recordId: recordId,
        objectApiName: 'Account',
        actionName: 'edit',
      },
    });
  }

  async handleDeleteRow(row) {
    if (!confirm(`Delete ${row.Name}?`)) {
      return;
    }

    this.isLoading = true;
    try {
      await deleteRecords({ recordIds: [row.Id] });
      this.showToast('Success', 'Record deleted', 'success');
      await this.refresh();
    } catch (error) {
      this.showToast('Error', this.reduceErrors(error), 'error');
    } finally {
      this.isLoading = false;
    }
  }

  // ═══════════════════════════════════════════════════════════════════════
  // INLINE EDITING
  // ═══════════════════════════════════════════════════════════════════════

  handleCellChange(event) {
    this.draftValues = event.detail.draftValues;
  }

  async handleSave(event) {
    const updatedFields = event.detail.draftValues;
    this.isLoading = true;

    try {
      await updateRecords({ records: updatedFields });
      this.showToast('Success', 'Records updated', 'success');
      this.draftValues = [];
      await this.refresh();
    } catch (error) {
      this.showToast('Error', this.reduceErrors(error), 'error');
    } finally {
      this.isLoading = false;
    }
  }

  handleCancel() {
    this.draftValues = [];
  }

  // ═══════════════════════════════════════════════════════════════════════
  // INFINITE SCROLLING
  // ═══════════════════════════════════════════════════════════════════════

  loadMoreData(event) {
    if (!this.enableInfiniteScroll) return;

    const { target } = event;
    target.isLoading = true;

    if (this.data.length >= this.totalRecords) {
      target.enableInfiniteLoading = false;
      this.loadMoreStatus = 'All records loaded';
      target.isLoading = false;
      return;
    }

    this.offset = this.data.length;
    // Wire will load more data
  }

  // ═══════════════════════════════════════════════════════════════════════
  // BULK ACTIONS
  // ═══════════════════════════════════════════════════════════════════════

  async handleBulkDelete() {
    if (!this.hasSelection) return;

    const selectedIds = this.selectedRows.map((row) => row.Id);

    if (!confirm(`Delete ${selectedIds.length} records?`)) {
      return;
    }

    this.isLoading = true;
    try {
      await deleteRecords({ recordIds: selectedIds });
      this.showToast('Success', `${selectedIds.length} records deleted`, 'success');
      this.selectedRows = [];
      await this.refresh();
    } catch (error) {
      this.showToast('Error', this.reduceErrors(error), 'error');
    } finally {
      this.isLoading = false;
    }
  }

  // ═══════════════════════════════════════════════════════════════════════
  // UTILITIES
  // ═══════════════════════════════════════════════════════════════════════

  async refresh() {
    this.isLoading = true;
    await refreshApex(this.wiredRecordsResult);
    this.isLoading = false;
  }

  handleRefresh() {
    this.refresh();
  }

  showToast(title, message, variant) {
    this.dispatchEvent(new ShowToastEvent({ title, message, variant }));
  }

  reduceErrors(errors) {
    if (!Array.isArray(errors)) errors = [errors];
    return errors
      .filter((e) => !!e)
      .map((e) => e.body?.message || e.message || JSON.stringify(e))
      .join(', ');
  }
}
