import * as plugins from '../plugins.js';
import * as appstate from '../appstate.js';
import * as shared from './shared/index.js';
import { appRouter } from '../router.js';

import {
  DeesElement,
  customElement,
  html,
  state,
  css,
  cssManager,
  type TemplateResult,
} from '@design.estate/dees-element';
import { DeesModal } from '@design.estate/dees-catalog';

@customElement('objst-view-buckets')
export class ObjstViewBuckets extends DeesElement {
  @state()
  accessor bucketsState: appstate.IBucketsState = { buckets: [] };

  constructor() {
    super();
    const sub = appstate.bucketsStatePart
      .select((s) => s)
      .subscribe((bucketsState) => {
        this.bucketsState = bucketsState;
      });
    this.rxSubscriptions.push(sub);
  }

  async connectedCallback() {
    super.connectedCallback();
    appstate.bucketsStatePart.dispatchAction(appstate.fetchBucketsAction, null);
  }

  public static styles = [
    cssManager.defaultStyles,
    shared.viewHostCss,
  ];

  public render(): TemplateResult {
    return html`
      <objst-sectionheading>Buckets</objst-sectionheading>
      <dees-table
        heading1="Buckets"
        heading2="Manage your storage buckets"
        .data=${this.bucketsState.buckets}
        .dataName=${'bucket'}
        .searchable=${true}
        .displayFunction=${(item: any) => ({
          name: item.name,
          objects: String(item.objectCount),
          size: this.formatBytes(item.totalSizeBytes),
          created: new Date(item.creationDate).toLocaleDateString(),
        })}
        .dataActions=${[
          {
            name: 'Create Bucket',
            iconName: 'lucide:plus',
            type: ['header'] as any[],
            actionFunc: async () => {
              await this.showCreateBucketModal();
            },
          },
          {
            name: 'Browse',
            iconName: 'lucide:folderOpen',
            type: ['inRow'] as any[],
            actionFunc: async (args: any) => {
              await appstate.objectsStatePart.dispatchAction(appstate.fetchObjectsAction, {
                bucketName: args.item.name,
                prefix: '',
                delimiter: '/',
              });
              appRouter.navigateToView('browser');
            },
          },
          {
            name: 'Policy',
            iconName: 'lucide:shield',
            type: ['inRow'] as any[],
            actionFunc: async (args: any) => {
              await this.showPolicyModal(args.item.name);
            },
          },
          {
            name: 'Delete',
            iconName: 'lucide:trash2',
            type: ['inRow', 'contextmenu'] as any[],
            actionFunc: async (args: any) => {
              await this.showDeleteBucketModal(args.item.name);
            },
          },
        ]}
      ></dees-table>
    `;
  }

  private async showCreateBucketModal(): Promise<void> {
    await DeesModal.createAndShow({
      heading: 'Create Bucket',
      content: html`
        <dees-form>
          <dees-input-text .key=${'bucketName'} .label=${'Bucket Name'} .required=${true}></dees-input-text>
        </dees-form>
      `,
      menuOptions: [
        {
          name: 'Cancel',
          action: async (modal: any) => { modal.destroy(); },
        },
        {
          name: 'Create',
          action: async (modal: any) => {
            const form = modal.shadowRoot.querySelector('dees-form') as any;
            const data = await form.collectFormData();
            if (data.bucketName) {
              await appstate.bucketsStatePart.dispatchAction(appstate.createBucketAction, {
                bucketName: data.bucketName,
              });
            }
            modal.destroy();
          },
        },
      ],
    });
  }

  private async showDeleteBucketModal(bucketName: string): Promise<void> {
    await DeesModal.createAndShow({
      heading: 'Delete Bucket',
      content: html`<p>Are you sure you want to delete bucket <strong>${bucketName}</strong>? This action cannot be undone.</p>`,
      menuOptions: [
        {
          name: 'Cancel',
          action: async (modal: any) => { modal.destroy(); },
        },
        {
          name: 'Delete',
          action: async (modal: any) => {
            await appstate.bucketsStatePart.dispatchAction(appstate.deleteBucketAction, {
              bucketName,
            });
            modal.destroy();
          },
        },
      ],
    });
  }

  private async showPolicyModal(bucketName: string): Promise<void> {
    const data = await appstate.getBucketNamedPolicies(bucketName);
    let modalRef: any = null;

    const renderContent = (
      attached: typeof data.attachedPolicies,
      available: typeof data.availablePolicies,
    ) => html`
      <style>
        .policy-lists { display: flex; flex-direction: column; gap: 16px; }
        .policy-section h4 {
          margin: 0 0 8px 0;
          font-size: 13px;
          font-weight: 600;
          color: ${cssManager.bdTheme('#333', '#ccc')};
        }
        .policy-item {
          display: flex;
          align-items: center;
          justify-content: space-between;
          padding: 8px 12px;
          border-radius: 6px;
          background: ${cssManager.bdTheme('#f5f5f5', '#1a1a2e')};
          margin-bottom: 4px;
          color: ${cssManager.bdTheme('#333', '#eee')};
        }
        .policy-item-info { display: flex; flex-direction: column; gap: 2px; }
        .policy-item-name { font-size: 14px; font-weight: 500; }
        .policy-item-desc { font-size: 12px; color: ${cssManager.bdTheme('#666', '#999')}; }
        .policy-item button {
          padding: 4px 12px;
          border-radius: 4px;
          border: none;
          cursor: pointer;
          font-size: 12px;
          font-weight: 500;
          flex-shrink: 0;
        }
        .btn-detach {
          background: ${cssManager.bdTheme('#ffebee', '#3e1a1a')};
          color: ${cssManager.bdTheme('#c62828', '#ef5350')};
        }
        .btn-detach:hover { opacity: 0.8; }
        .btn-attach {
          background: ${cssManager.bdTheme('#e3f2fd', '#1a2a3e')};
          color: ${cssManager.bdTheme('#1565c0', '#64b5f6')};
        }
        .btn-attach:hover { opacity: 0.8; }
        .empty-note {
          color: ${cssManager.bdTheme('#999', '#666')};
          font-size: 13px;
          font-style: italic;
          padding: 8px 0;
        }
      </style>
      <div class="policy-lists">
        <div class="policy-section">
          <h4>Attached Policies (${attached.length})</h4>
          ${attached.length > 0
            ? attached.map((policy) => html`
                <div class="policy-item">
                  <div class="policy-item-info">
                    <span class="policy-item-name">${policy.name}</span>
                    ${policy.description ? html`<span class="policy-item-desc">${policy.description}</span>` : ''}
                  </div>
                  <button class="btn-detach" @click=${async (e: Event) => {
                    (e.target as HTMLButtonElement).disabled = true;
                    await appstate.detachPolicyFromBucket(policy.id, bucketName);
                    const fresh = await appstate.getBucketNamedPolicies(bucketName);
                    if (modalRef) {
                      modalRef.content = renderContent(fresh.attachedPolicies, fresh.availablePolicies);
                    }
                  }}>Detach</button>
                </div>
              `)
            : html`<p class="empty-note">No policies attached to this bucket.</p>`}
        </div>
        <div class="policy-section">
          <h4>Available Policies (${available.length})</h4>
          ${available.length > 0
            ? available.map((policy) => html`
                <div class="policy-item">
                  <div class="policy-item-info">
                    <span class="policy-item-name">${policy.name}</span>
                    ${policy.description ? html`<span class="policy-item-desc">${policy.description}</span>` : ''}
                  </div>
                  <button class="btn-attach" @click=${async (e: Event) => {
                    (e.target as HTMLButtonElement).disabled = true;
                    await appstate.attachPolicyToBucket(policy.id, bucketName);
                    const fresh = await appstate.getBucketNamedPolicies(bucketName);
                    if (modalRef) {
                      modalRef.content = renderContent(fresh.attachedPolicies, fresh.availablePolicies);
                    }
                  }}>Attach</button>
                </div>
              `)
            : html`<p class="empty-note">${attached.length > 0
                ? 'All policies are already attached.'
                : 'No policies defined yet. Create policies in the Policies view.'
              }</p>`}
        </div>
      </div>
    `;

    modalRef = await DeesModal.createAndShow({
      heading: `Policies for: ${bucketName}`,
      content: renderContent(data.attachedPolicies, data.availablePolicies),
      menuOptions: [
        { name: 'Done', action: async (modal: any) => { modal.destroy(); } },
      ],
    });
  }

  private formatBytes(bytes: number): string {
    if (bytes === 0) return '0 B';
    const units = ['B', 'KB', 'MB', 'GB', 'TB'];
    const i = Math.floor(Math.log(bytes) / Math.log(1024));
    return `${(bytes / Math.pow(1024, i)).toFixed(1)} ${units[i]}`;
  }
}
