import '@things-factory/grist-ui'

import gql from 'graphql-tag'
import {
  css,
  html,
  LitElement
} from 'lit-element'

import {
  i18next,
  localize
} from '@things-factory/i18n-base'
import {
  client,
  CustomAlert
} from '@things-factory/shell'
import { ScrollbarStyles } from '@things-factory/styles'
import { isMobileDevice } from '@things-factory/utils'

export class ProceedEditVasPopup extends localize(i18next)(LitElement) {
	static get styles() {
		return [
			ScrollbarStyles,
			css`
				:host {
					display: flex;
					flex-direction: column;
					overflow: hidden;
					background-color: white;
				}
				.grist-container {
					overflow-y: auto;
					display: flex;
					flex: 1;
					margin: 10px;
				}
				.grist {
					display: flex;
					flex-direction: column;
					flex: 1;
					overflow-y: auto;
				}
				.grist h2 mwc-icon {
					vertical-align: middle;
					margin: var(--grist-title-icon-margin);
					font-size: var(--grist-title-icon-size);
					color: var(--grist-title-icon-color);
				}
				data-grist {
					overflow-y: hidden;
					flex: 1;
				}
				h2 {
					padding: var(--subtitle-padding);
					font: var(--subtitle-font);
					color: var(--subtitle-text-color);
					border-bottom: var(--subtitle-border-bottom);
				}
				.grist h2 {
					font: var(--grist-title-font);
				}
				.button-container {
					padding: var(--button-container-padding);
					margin: var(--button-container-margin);
					text-align: var(--button-container-align);
					background-color: var(--button-container-background);
					height: var(--button-container-height);
				}
				[danger] {
					--mdc-theme-primary: var(--mdc-danger-button-primary-color);
				}
			`
		]
	}

	static get properties() {
		return {
			config: Object,
			data: Object,
			bizplace: String,
			releaseGoodNo: String
		}
	}

	render() {
		return html`
			<div class="grist-container">
				<div class="grist">
					<h2><mwc-icon>list-alt</mwc-icon>${i18next.t('title.approve')}</h2>
					<data-grist
						id="approve-grist"
						.mode="${isMobileDevice() ? 'LIST' : 'GRID' }"
						.config="${this.config}"
						.data="${this.approvedData}"
					></data-grist>
				</div>

				<div class="grist">
					<h2><mwc-icon>list-alt</mwc-icon>${i18next.t('title.reject')}</h2>
					<data-grist
						id="reject-grist"
						.mode="${isMobileDevice() ? 'LIST' : 'GRID' }"
						.config="${this.config}"
						.data="${this.rejectedData}"
					></data-grist>
				</div>
			</div>

			<div class="button-container">
        <mwc-button
          raised
          @click="${this._approveVasChanges.bind(this)}"
          label="${i18next.t('button.approve')}"
        ></mwc-button>
        <mwc-button
          raised
          danger
          @click="${this._rejectVasChanges.bind(this)}"
          label="${i18next.t('button.reject')}"
        ></mwc-button>
        <mwc-button
          raised
          @click="${this._proceedEditedVas.bind(this)}"
          label="${i18next.t('button.confirm')}"
        ></mwc-button>
      </div>
		`
	}

	constructor() {
		super()
		this.approvedData = { records: [] }
		this.rejectedData = { records: [] }
	}

	get approveGrist() {
		return this.shadowRoot.querySelector('data-grist#approve-grist')
	}

	get rejectGrist() {
		return this.shadowRoot.querySelector('data-grist#reject-grist')
	}

	updated(changedProps) {
		if (changedProps.has('data')) {
			this.approvedData = {
				...this.data,
				records: this.data.records.filter(
					item => item.editType || item.itemEditType
				)
			}
		}
	}

	firstUpdated() {
		this.config = {
			list: {
				fields: [
					'itemEditType',
					'batchId',
          'productSKU',
					'adjustedBatchId',
					'adjustedSku',
          'qty',
					'adjustedQty',
          'packingType',
					'adjustedPackingType',
          'uom',
					'adjustedUom',
          'uomValue',
					'adjustedUomValue',
          'vas',
          'vasQty',
					'adjustedVasQty',
					'newBatchId',
					'adjustedNewBatchId',
          'newSKU',
					'adjustedNewSku',
          'newPackingType',
					'adjustedNewPackingType',
          'newUom',
					'adjustedNewUom',
					'newUnitUomValue',
					'adjustedNewUnitUomValue',
          'newUomValue',
					'adjustedNewUomValue',
          'outputQty',
					'adjustedOutputQty',
          'vasRemark',
					'adjustedVasRemark',
				]
			},
			pagination: { infinite: true },
			rows: { 
				selectable: {multiple: true }, 
				groups: { column: 'productSKU' },
				appendable: false,
			},
			columns: [
				{ type: 'gutter', gutterName: 'sequence' },
				{ 
					type: 'gutter', 
					gutterName: 'row-selector', 
					multiple: true
				},
				{
					type: 'string',
					name: 'itemEditType',
					header: i18next.t('field.type'),
					width: 100
				},
				{
					type: 'string',
					name: 'batchId',
					header: i18next.t('field.batch_no'),
					width: 150
				},
				{
					type: 'string',
					name: 'adjustedBatchId',
					header: i18next.t('field.adjusted_batch_id'),
					width: 150
				},
				{
					type: 'string',
					name: 'productSKU',
					header: i18next.t('field.sku'),
					width: 150
				},
				{
					type: 'string',
					name: 'adjustedSku',
					header: i18next.t('field.adjusted_sku'),
					width: 150
				},
				{
					type: 'integer',
					name: 'qty',
					header: i18next.t('field.qty'),
					width: 100
				},
				{
					type: 'string',
					name: 'adjustedQty',
					header: i18next.t('field.adjusted_qty'),
					width: 100
				},
				{
					type: 'string',
					name: 'packingType',
					header: i18next.t('field.packing_type_sku', { sku: 'SKU' }),
					width: 150
				},
				{
					type: 'string',
					name: 'adjustedPackingType',
					header: i18next.t('field.adjusted_packing_type_sku', { sku: 'SKU' }),
					width: 150
				},
				{
					type: 'string',
					name: 'uom',
					header: i18next.t('field.uom_sku', { sku: 'SKU' }),
					width: 100
				},
				{
					type: 'string',
					name: 'adjustedUom',
					header: i18next.t('field.adjusted_uom', { sku: 'SKU'}),
					width: 100
				},
				{
					type: 'integer',
					name: 'uomValue',
					header: i18next.t('field.uom_value_sku', { sku: 'SKU' }),
					width: 100
				},
				{
					type: 'integer',
					name: 'adjustedUomValue',
					header: i18next.t('field.adjusted_uom_value_sku', { sku: 'SKU' }),
					width: 100
				},
				{
					type: 'string',
					name: 'group',
					hidden: true
				},
				{
					type: 'string',
					name: 'orderVasItemId',
					hidden: true,
				},
				{
					type: 'object',
					name: 'vas',
					header: i18next.t('field.vas'),
					width: 250
				},
				{
					type: 'integer',
					name: 'vasQty',
					header: i18next.t('field.vas_qty'),
					width: 80
				},
				{
					type: 'integer',
					name: 'adjustedVasQty',
					header: i18next.t('field.adjusted_vas_qty'),
					width: 80
				},
				{
					type: 'string',
					name: 'newBatchId',
					header: i18next.t('field.batch_no_(new_sku)'),
					width: 150
				},
				{
					type: 'string',
					name: 'adjustedNewBatchId',
					header: i18next.t('field.adjusted_batch_id_new_sku'),
					width: 150
				},
				{
					type: 'string',
					name: 'newSku',
					header: i18next.t('field.new_sku'),
					width: 200
				},
				{
					type: 'string',
					name: 'adjustedNewSku',
					header: i18next.t('field.adjusted_new_sku'),
					width: 200
				},
				{
					type: 'string',
					name: 'newPackingType',
					header: i18next.t('field.packing_type_sku', { sku: 'N. SKU' }),
					width: 150
				},
				{
					type: 'string',
					name: 'adjustedNewPackingType',
					header: i18next.t('field.adjusted_packing_type_sku', { sku: 'N. SKU' }),

					width: 150
				},
				{
					type: 'string',
					name: 'newUom',
					header: i18next.t('field.uom_sku', { sku: 'N.SKU' }),
					width: 80
				},
				{
					type: 'string',
					name: 'adjustedNewUom',
					header: i18next.t('field.adjusted_uom_sku', { sku: 'N.SKU' }),
					width: 80
				},
				{
					type: 'float',
					name: 'newUnitUomValue',
					header: i18next.t('field.uom_value_sku', { sku: 'NEW SKU' }),
					width: 150
				},
				{
					type: 'float',
					name: 'adjustedNewUnitUomValue',
					header: i18next.t('field.adjusted_uom_value_sku', { sku: 'NEW SKU' }),
					width: 150
				},
				{
					type: 'float',
					name: 'newUomValue',
					header: i18next.t('field.total_uom_value_sku', { sku: 'N.SKU' }),
					width: 150
				},
				{
					type: 'float',
					name: 'adjustedNewUomValue',
					header: i18next.t('field.adjusted_total_uom_value_sku', { sku:'N.SKU' }),
					width: 150
				},
				{
					type: 'integer',
					name: 'outputQty',
					header: i18next.t('field.output_qty'),
					width: 100
				},
				{
					type: 'integer',
					name: 'adjustedOutputQty',
					header: i18next.t('field.adjusted_output_qty'),
					width: 100
				},
				{
					type: 'string',
					name: 'vasRemark',
					header: i18next.t('field.remark'),
					width: 400
				},
				{
					type: 'string',
					name: 'adjustedVasRemark',
					header: i18next.t('field.adjusted_vas_remark'),
					width: 400
				}
			]
		}
	}

	async _approveVasChanges() {
		if (!this.rejectGrist.selected || !this.rejectGrist.selected.length) return
		
		const selectedGroups = this.rejectGrist.selected.map(record => record.group)
		
		const approvedData = [
			...this.approveGrist.data.records,
			...this.rejectGrist.data.records.filter(record => 
				selectedGroups.some(group => group === record.group)
			)
		]
		
		const rejectedData = this.rejectGrist.data.records.filter(record => 
			!selectedGroups.some(group => group === record.group)
		)
	
		this.approveGrist.data = { records: [] }
		this.rejectGrist.data = { records: [] }
	
		await this.approveGrist.updateComplete
		await this.rejectGrist.updateComplete
	
		this.approveGrist.data = { records: approvedData }
		this.rejectGrist.data = { records: rejectedData }
	}
	
	async _rejectVasChanges() {
		if (!this.approveGrist.selected || !this.approveGrist.selected.length) return
		
		const selectedGroups = this.approveGrist.selected.map(record => record.group)
		
		const rejectedData = [
			...this.rejectGrist.data.records,
			...this.approveGrist.data.records.filter(record => 
				selectedGroups.some(group => group === record.group)
			)
		]
		
		const approvedData = this.approveGrist.data.records.filter(record => 
			!selectedGroups.some(group => group === record.group)
		)
	
		this.approveGrist.data = { records: [] }
		this.rejectGrist.data = { records: [] }
	
		await this.approveGrist.updateComplete
		await this.rejectGrist.updateComplete
	
		this.approveGrist.data = { records: approvedData }
		this.rejectGrist.data = { records: rejectedData }
	}

	async _proceedEditedVas() {
		try {
      const result = await CustomAlert({
        title: i18next.t('title.are_you_sure'),
        text: i18next.t('text.you_wont_be_able_to_revert_this'),
        confirmButton: { text: i18next.t('button.confirm') },
        cancelButton: { text: i18next.t('button.cancel') }
      })

			if (!result.value) return
			
			const response = await client.mutate({
				mutation: gql`
					mutation proceedVasChanges(
						$releaseOrderNo: String!
						$bizplaceId: String!
						$approvedVas: [OrderVasPatch!]
						$rejectedVas: [OrderVasPatch!]
					) {
						proceedVasChanges(
							releaseOrderNo: $releaseOrderNo
							bizplaceId: $bizplaceId
							approvedVas: $approvedVas
							rejectedVas: $rejectedVas
						)	
					}
				`,
				variables: {
					releaseOrderNo: this.releaseGoodNo,
					bizplaceId: this.bizplace,
					approvedVas: await this._getApprovedVas(),
					rejectedVas: await this._getRejectedVas()
				}
			})

			if (!response.errors) {
        this._showToast({ message: i18next.t('text.vas_changes_has_been_processed') })
        this.dispatchEvent(new CustomEvent('completed'))
        window.history.back()
      }
		} catch(e) {
			this._showToast({ message: e.message })
		}
	}

	_getApprovedVas() {
		return this.approveGrist?.dirtyData.records
		.map(ov => {
			return {
				id: ov?.id,
				editType: ov.editType,
				orderVasItemsPatch: this.approveGrist.dirtyData.records.reduce((acc, cur) => {
					if (cur.group === ov.group) {
						return [...acc, { id: cur?.orderVasItemId, itemEditType: cur?.itemEditType }]
					} else {
						return acc
					}
				}, [])
			}
		})
		.filter(ov => ov.id)
	}

	_getRejectedVas() {
		return this.rejectGrist.dirtyData.records
		.map(ov => {
			return {
				id: ov?.id,
				editType: ov.editType,
				orderVasItemsPatch: this.rejectGrist.dirtyData.records.reduce((acc, cur) => {
					if (cur.group === ov.group) {
						return [...acc, { id: cur?.orderVasItemId, itemEditType: cur?.itemEditType }]
					} else {
						return acc
					}
				}, []),
			}
		})
		.filter(ov => ov.id)
	}

	_showToast({ type, message }) {
    document.dispatchEvent(
      new CustomEvent('notify', {
        detail: {
          type,
          message
        }
      })
    )
  }
}

window.customElements.define('proceed-edit-vas-popup', ProceedEditVasPopup)