import { componentName } from '../src/components/descope-grid';
import {
  borderedControl,
  sizeControl,
  overrideRenderItemControl,
  directionControl,
} from './commonControls';

const userStatuses = ['active', 'disabled', 'invited'];

const xml = `
<Response xmlns="urn:oasis:names:tc:SAML:2.0:protocol" ID="111" InResponseTo="b6aa8" Destination="https://api.descope.org/v1/auth/saml/acs?projectId=123&amp;tenantId=456" Version="2.0" IssueInstant="2024-09-03T08:19:40.649Z">
  <Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0" ID="222" IssueInstant="2024-09-03T08:19:40.649Z">
    <AttributeStatement xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
      <Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="" Name="email" NameFormat="">
        <AttributeValue xmlns="urn:oasis:names:tc:SAML:2.0:assertion" xsi:type="">xxx@descope.com</AttributeValue>
      </Attribute>
      <Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="" Name="Groups" NameFormat="">
        <AttributeValue xmlns="urn:oasis:names:tc:SAML:2.0:assertion" xsi:type="">aws-sandbox</AttributeValue>
        <AttributeValue xmlns="urn:oasis:names:tc:SAML:2.0:assertion" xsi:type="">dev</AttributeValue>
      </Attribute>
    </AttributeStatement>
  </Assertion>
</Response>
`;

const mockUserData = (n) =>
  Array(n)
    .fill()
    .map((_, idx) => ({
      loginId: `login${idx}@company.com`,
      email: `email${idx}@company.com`,
      phone: `+1-${idx}-12345`,
      displayName: `Joe #${idx}`,
      userTenants: [
        {
          tenantId: `${idx}`,
          roleNames: ['TestRole'],
        },
      ],
      customAttributes: {
        attribute1: `${idx}A`,
        attribute2: `${idx}B`,
      },
      xml,
      picture: `https://dummyimage.com/50x50/000/fff`,
      verifiedEmail: true,
      verifiedPhone: true,
      test: false,
      status: userStatuses[idx % 3],
    }));

const altRenderColumn = ({ path, header, type, attrs = {} }) => {
  const colAttrs = Object.entries(attrs)
    .map((pair) => `${pair[0]}="${pair[1] || ''}"`)
    .join(' ');

  return `<descope-grid-${type}-column path="${path}" header="${header} (custom)" ${colAttrs}></descope-grid-${type}-column>`;
};

const columnsData = [
  {
    path: '',
    header: '',
    type: 'selection',
    attrs: { frozen: 'true', 'auto-width': '' },
  },
  {
    path: 'loginId',
    header: 'Login ID',
    type: 'text',
    attrs: { resizable: '', 'auto-width': '' },
  },
  {
    path: 'status',
    header: 'Status',
    type: 'custom',
    attrs: { resizable: '', 'auto-width': '', status: 'Active,Inactive' },
  },
  {
    path: 'displayName',
    header: 'Name',
    type: 'text',
    attrs: { resizable: '', 'auto-width': '' },
  },
  {
    path: 'email',
    header: 'Email',
    type: 'text',
    attrs: { resizable: '', 'auto-width': '' },
  },
  {
    path: 'phone',
    header: 'Phone',
    type: 'text',
    attrs: { resizable: '', 'auto-width': '' },
  },
  {
    path: '',
    header: '',
    type: 'item-details',
    attrs: { 'frozen-to-end': 'true', 'auto-width': '' },
  },
];

const Template = ({ data, bordered, size, columnsSyncProp, containerHeight, direction }) => {
  let serializedData;

  try {
    serializedData = JSON.stringify(data);
  } catch (e) {
    // do nothing
  }

  const columnsTemplate = `
    <descope-grid-selection-column frozen auto-width></descope-grid-selection-column>
    <descope-grid-text-column path="loginId" header="Login ID" resizable auto-width></descope-grid-text-column>
    <descope-grid-custom-column sortable="true" path="status" header="Status" resizable>
      <descope-badge mode="default" data-pattern="invited" bordered="true" size="xs" st-text-transform="capitalize"></descope-badge>
      <descope-badge mode="primary" data-pattern="active" bordered="true" size="xs" st-text-transform="capitalize"></descope-badge>
      <descope-badge mode="error" data-pattern="disabled" bordered="true" size="xs" st-text-transform="capitalize"></descope-badge>
    </descope-grid-custom-column>
    <descope-grid-text-column sortable="true" path="displayName" header="Name" resizable auto-width></descope-grid-text-column>
    <descope-grid-text-column sortable="true" path="email" header="Email" resizable auto-width></descope-grid-text-column>
    <descope-grid-text-column sortable="true" path="phone" header="Phone" resizable auto-width></descope-grid-text-column>
    <descope-grid-item-details-column auto-width frozen-to-end></descope-grid-item-details-column>
  `;

  return `
    <style nonce=${window.DESCOPE_NONCE}>
      .wrapper {
        height: ${containerHeight};
      }
    </style>
    <div class="wrapper">
      <descope-grid
        st-host-direction="${direction ?? ''}"
        bordered="${bordered}"
        size="${size}"
        columns='${columnsSyncProp === 'attribute' ? JSON.stringify(columnsData) : ''}'
        column-reordering-allowed
        identifier="loginId"
      >
        ${columnsSyncProp === 'template' ? columnsTemplate : ''}
      </descope-grid>
    </div>
  `;
};

export default {
  component: componentName,
  title: 'descope-grid',
  decorators: [
    (story, { args }) => {
      const observer = new MutationObserver(() => {
        const ele = document.querySelector('descope-grid');
        if (!ele) return;

        observer.disconnect();

        if (args.overrideRenderItem) {
          ele.renderColumn = altRenderColumn;
        }

        if (args.itemsSyncProp === 'propSync') {
          ele.data = args.data;
        } else {
          setTimeout(() => {
            ele.data = args.data;
          }, 500);
        }

        if (args.columnsSyncProp === 'propSync') {
          ele.columns = columnsData;
        } else if (args.columnsSyncProp === 'propAsync') {
          setTimeout(() => {
            ele.columns = columnsData;
          }, 500);
        }
      });

      observer.observe(document.body, {
        childList: true,
        subtree: true,
      });

      return story();
    },
  ],
  argTypes: {
    ...sizeControl,
    ...borderedControl,
    ...overrideRenderItemControl,
    ...directionControl,
    columnsSyncProp: {
      name: 'Columns Source',
      options: ['none', 'attribute', 'template', 'propSync', 'propAsync'],
      control: { type: 'select' },
    },
    itemsSyncProp: {
      name: 'Items Source',
      options: ['propSync', 'propAsync'],
      control: { type: 'select' },
    },
  },
};

export const Default = Template.bind({});

Default.args = {
  size: 'md',
  itemsSyncProp: 'propSync',
  columnsSyncProp: 'template',
  overrideRenderItem: false,
  containerHeight: '400px',
  bordered: true,
  data: mockUserData(25),
};
