<script>
    class Venta {
        props = {
            id: 0,
            fecha: null,
            last: {
                november: null
            },
            valor: 0,
            inmobiliaria: {
                rut: '',
                nombre: '',
                direccion: '',
                comuna: ''
            },
            proyecto: {
                id: 0
            },
            uf: {
               fecha: null,
               valor: 0
            },
            ipc: {
                fecha: null,
                valor: 0
            },
            unidades: [],
            facturas: {
                fecha: null,
                terreno: {
                    fecha: null,
                    valor: 0
                },
                facturas: []
            },
            propietarios: [],
            estado: {
                fecha: null
            }
        }

        constructor(props) {
            this.props = props
        }

        get prorrateo() {
            return this.props.unidades.reduce((sum, unidad) => sum + unidad.props.prorrateo, 0.0)
        }

        update() {
            return {
                propietarios: count => {
                    const diff = count - this.props.propietarios.length
                    if (diff > 0) {
                        const m = this.props.propietarios.length / count
                        let p = 1
                        this.props.propietarios.forEach((propietario, index) => {
                            this.props.propietarios[index].props.proporcion = parseFloat((this.props.propietarios[index].props.proporcion * m * 100).toFixed(0)) / 100
                            p -= this.props.propietarios[index].props.proporcion
                        })
                        p /= diff
                        const propietarios = []
                        for (let i = 0; i < diff; i ++) {
                            propietarios.push(this.add().propietario({
                                rut: '',
                                nombre: '',
                                proporcion: (p*100).toFixed(0)/100,
                                direccion: '',
                                comuna: ''
                            }))
                        }
                        document.getElementById('propietarios').innerHTML = this.draw().propietarios()
                        propietarios.forEach(propietario => {
                            this.add().factura(propietario)
                        })
                        this.watch().propietarios()
                        this.update().facturas()
                        return
                    }
                    for (let i = this.props.propietarios.length - 1; i >= count; i --) {
                        this.remove().propietario(i)
                    }
                },
                fecha: date => {
                    this.props.uf.fecha = date
                    const url = '{{$urls->api}}/money/uf'
                    const method = 'post'
                    const body = new FormData()
                    body.set('fecha', [date.getFullYear(), date.getMonth()+1, date.getDate()].join('-'))
                    return fetchAPI(url, {method, body}).then(response => {
                        if (!response) {
                            return
                        }
                        return response.json().then(json => {
                            if (typeof json.uf === 'undefined') {
                                return
                            }
                            this.props.uf.valor = json.uf

                            return this.update().ipc()
                        })
                    })
                },
                fechaFacturas: date => {
                    if (this.props.facturas.fecha === date) {
                        return
                    }
                    this.props.facturas.fecha = date
                    this.update().facturas()
                    return new Promise(resolve => resolve())
                },
                totalUnidades: () => {
                    const unidades = this.props.unidades.reduce((sum, unidad) => sum + unidad.props.valor, 0)
                    const diff = parseFloat((this.props.valor - unidades).toFixed(4))
                    const $total = $('#total_unidades')
                    if (diff === 0) {
                        $total.html('')
                        return
                    }
                    $total.html('<div class="ui error compact message">' +
                        '<div class="header">' +
                        '<i class="exclamation triangle icon"></i>' +
                        'Diferencia Promesa - Precio Unidades</div>' +
                        'UF ' + facturas.formatters.ufs.format(diff) +
                        '</div>')
                    $total.find('.ui.message').css('display', 'inline-block')

                    this.update().facturas()
                },
                terreno: newValue => {
                    const date = this.props.last.november

                    const url = '{{$urls->api}}/proyecto/{{$venta->proyecto()->id}}/terreno/edit'
                    const method = 'post'
                    const body = new FormData()
                    body.set('valor', newValue)
                    body.set('fecha', [date.getFullYear(), date.getMonth()+1, date.getDate()].join('-'))
                    return fetchAPI(url, {method, body}).then(response => {
                        if (!response) {
                            return
                        }
                        return response.json().then(json => {
                            if (!json.success) {
                                return
                            }
                            this.props.facturas.terreno.fecha = new Date(json.terreno.fecha)
                            this.props.facturas.terreno.valor = parseInt(json.terreno.valor)

                            document.getElementById('terreno').parentElement.parentElement.remove()

                            this.update().ipc()
                        })
                    })
                },
                ipc: () => {
                    const mesAnterior = new Date([this.props.facturas.fecha.getFullYear(), this.props.facturas.fecha.getMonth()-1, '1'].join('-'))
                    if (this.props.last.november.getMonth() === mesAnterior.getMonth() && this.props.last.november.getFullYear() === mesAnterior.getFullYear()) {
                        return
                    }
                    const url = '{{$urls->api}}/money/ipc'
                    const method = 'post'
                    const body = new FormData()
                    body.set('start', [this.props.last.november.getFullYear(), this.props.last.november.getMonth()+1, this.props.last.november.getDate()].join('-'))
                    body.set('end', [mesAnterior.getFullYear(), mesAnterior.getMonth()+1, mesAnterior.getDate()].join('-'))
                    return fetchAPI(url, {method, body}).then(response => {
                        if (!response) {
                            return
                        }
                        return response.json().then(json => {
                            this.props.ipc = json.ipc
                            this.props.facturas.terreno.valor *= (1 + parseFloat(json.ipc.valor))
                            this.update().facturas()
                        })
                    })
                },
                facturas: () => {
                    this.props.facturas.facturas.forEach(factura => {
                        factura.update().venta(this)
                    })
                },
                form: () => {
                    // fecha
                    // unidades
                    // valor total unidades
                    // terreno
                    // propietarios
                    // ipc no disponible
                }
            }
        }
        watch() {
            return {
                venta: () => {
                    this.watch().fecha()
                    this.watch().fechaFacturas()
                    this.watch().unidades()
                    this.watch().terreno()
                    this.watch().cantidad()
                    this.watch().propietarios()
                    this.update().totalUnidades()
                },
                fecha: () => {
                    const cdo = structuredClone(calendar_date_options)
                    cdo['initialDate'] = this.props.estado.fecha
                    cdo['onChange'] = (date, text, mode) => {
                        this.update().fecha(date).then(() => {
                            facturas.draw().facturas()
                        })
                    }
                    $('#fecha_uf').calendar(cdo)
                },
                fechaFacturas: () => {
                    const cdo = structuredClone(calendar_date_options)
                    cdo['initialDate'] = this.props.estado.fecha
                    cdo['onChange'] = (date, text, mode) => {
                        this.update().fechaFacturas(date).then(() => {
                            facturas.draw().facturas()
                        })
                    }
                    $('#fecha_facturas').calendar(cdo)
                },
                unidades: () => {
                    this.props.unidades.forEach(unidad => {
                        unidad.watch().unidad()
                    })
                },
                terreno: () => {
                    const terreno = document.getElementById('terreno')
                    if (typeof terreno === 'undefined' || terreno === null) {
                        return
                    }
                    terreno.addEventListener('change', changeEvent => {
                        const newValue = changeEvent.currentTarget.value
                        if (newValue === this.props.facturas.terreno.valor) {
                            return
                        }
                        this.update().terreno(newValue)
                    })
                },
                cantidad: () => {
                    document.getElementById('cantidad_propietarios').addEventListener('change', changeEvent => {
                        const count = changeEvent.currentTarget.value
                        const diff = count - this.props.propietarios.length
                        if (diff === 0) {
                            return
                        }
                        this.update().propietarios(count)
                        facturas.draw().facturas()
                    })
                },
                propietarios: () => {
                    this.props.propietarios.forEach(propietario => {
                        propietario.watch().propietario()
                    })
                },
                facturas: () => {
                    this.props.facturas.facturas.forEach(factura => {
                        factura.watch().save()
                    })
                }
            }
        }
        draw() {
            return {
                venta: ufFormatter => {
                    return [
                        this.draw().value(ufFormatter),
                        this.draw().form(),
                        this.draw().ipc()
                    ].join("\n")
                },
                value: ufFormatter => {
                    return [
                        '<div class="ui grid">',
                            '<div class="three wide column">',
                                '<div class="ui very segment">',
                                    'Valor Venta: UF ' + ufFormatter.format(this.props.valor),
                                '</div>',
                            '</div>',
                        '</div>'
                    ].join("\n")
                },
                form: () => {
                    const output = []
                    output.push('<form id="venta_form" class="ui form">')
                    output.push(this.draw().fecha())
                    output.push(this.draw().fechaFactura())
                    output.push(this.draw().precios())
                    output.push(this.draw().prorrateos())
                    output.push('<div class="ui very basic segment" id="total_unidades"></div>')
                    output.push(this.draw().terreno())
                    output.push(...[
                        '<div class="two wide field">',
                        '<label for="propietarios">Propietarios</label>',
                        '<input type="number" name="cantidad_propietarios" id="cantidad_propietarios" min="1" value="1" />',
                        '</div>',
                    ])
                    output.push('<div id="propietarios">')
                    output.push(this.draw().propietarios())
                    output.push('</div>')
                    output.push('</form>')
                    return output.join("\n")
                },
                fecha: () => {
                    return [
                        '<div class="three wide field">',
                        '<label for="fecha_uf">Fecha UF</label>',
                        '<div class="ui calendar" id="fecha_uf">',
                        '<div class="ui right icon input">',
                        '<input type="text" name="fecha_uf" />',
                        '<i class="calendar icon"></i>',
                        '</div>',
                        '</div>',
                        '</div>',
                    ].join("\n")
                },
                fechaFactura: () => {
                    return [
                        '<div class="three wide field">',
                        '<label for="fecha_uf">Fecha Facturas</label>',
                        '<div class="ui calendar" id="fecha_facturas">',
                        '<div class="ui right icon input">',
                        '<input type="text" name="fecha_facturas" />',
                        '<i class="calendar icon"></i>',
                        '</div>',
                        '</div>',
                        '</div>',
                    ].join("\n")
                },
                precios: () => {
                    const output = []
                    output.push('<div class="fields">')
                    this.props.unidades.forEach(unidad => {
                        output.push(unidad.draw().precio())
                    })
                    output.push('</div>')
                    return output.join("\n")
                },
                prorrateos: () => {
                    const output = []
                    output.push('<div class="fields">')
                    this.props.unidades.forEach(unidad => {
                        output.push(unidad.draw().prorrateo())
                    })
                    output.push('</div>')
                    return output.join("\n")
                },
                terreno: () => {
                    const output = []
                    if (typeof this.props.facturas.terreno.fecha === 'undefined' || this.props.facturas.terreno.fecha === null || this.props.facturas.terreno.fecha.getTime() < 0 || this.props.facturas.terreno.fecha < this.props.last.november) {
                        output.push(...[
                            '<div class="four wide field">',
                            '<label for="terreno">Valor Terreno al '+this.props.last.november.toString()+'</label>',
                            '<div class="ui left labeled input">',
                            '<div class="ui basic label">$</div>',
                            '<input type="number" id="terreno" />',
                            '</div>',
                            '</div>'
                        ])
                    }
                    return output.join("\n")
                },
                propietarios: () => {
                    const output = []
                    this.props.propietarios.forEach(propietario => {
                        output.push(propietario.draw().propietario())
                    })
                    return output.join("\n")
                },
                ipc: () => {
                    if (!(this.props.fecha > this.props.facturas.terreno.fecha && this.props.facturas.terreno.valor === 0)) {
                        return ''
                    }
                    return [
                        '<div class="ui compact icon error message">',
                        '<i class="exclamation triangle icon"></i>',
                        '<div class="content">',
                        'IPC no disponible para este mes.',
                        '</div>',
                        '</div>'
                    ].join("\n")
                },
                facturas: formatters => {
                    const output = []
                    this.props.facturas.facturas.forEach(factura => {
                        output.push(factura.draw().factura({formatters}))
                    })
                    return output.join("\n")
                }
            }
        }
        add() {
            return {
                propietario: ({rut, nombre, proporcion, direccion, comuna}) => {
                    const index = this.props.propietarios.length + 1
                    const propietario = new Propietario({index, proporcion, rut, nombre, direccion, comuna})
                    this.props.propietarios.push(propietario)
                    return propietario
                },
                factura: propietario => {
                    const factura = new Factura({
                        id: 0,
                        venta: this.props,
                        index: propietario.props.index,
                        proporcion: propietario.props.proporcion,
                        terreno: this.props.facturas.terreno,
                        emisor: {
                            rut: this.props.inmobiliaria.rut,
                            nombre: this.props.inmobiliaria.nombre,
                            direccion: this.props.inmobiliaria.direccion,
                            comuna: this.props.inmobiliaria.comuna
                        },
                        receptor: {
                            rut: propietario.props.rut ?? '',
                            nombre: propietario.props.nombre ?? '',
                            direccion: propietario.props.direccion ?? '',
                            comuna: propietario.props.comuna ?? ''
                        },
                        unidades: [],
                        detalle: {
                            total: this.props.valor * this.props.uf.valor * propietario.props.proporcion,
                            base: 0,
                            terreno: 0,
                            neto: 0,
                            iva: 0,
                            bruto: 0,
                            descuento: 0,
                        },
                        total: {
                            neto: 0,
                            exento: 0,
                            iva: 0,
                            total: this.props.valor * this.props.uf.valor * propietario.props.proporcion
                        },
                        uf: this.props.uf
                    })
                    factura.update().venta(this)
                    this.props.facturas.facturas.push(factura)
                }
            }
        }
        remove() {
            return {
                propietario: index => {
                    if (index <= 0) {
                        return
                    }
                    const P1 = this.props.propietarios.reduce((sum, propietario) => sum + propietario.props.proporcion, 0)
                    const propietario = this.props.propietarios.splice(index, 1)[0]
                    const P2 = this.props.propietarios.reduce((sum, propietario) => sum + propietario.props.proporcion, 0)
                    document.querySelectorAll("[data-index='"+propietario.props.index+"']").forEach(field => {
                        field.remove()
                    })
                    this.remove().factura(index)
                },
                factura: index => {
                    this.props.facturas.facturas.splice(index, 1)
                    document.getElementById('facturas').querySelectorAll("[data-index='"+(index+1)+"']").forEach(factura => {
                        factura.remove()
                    })
                }
            }
        }
        save() {
            return {
                factura: ({index}) => {
                    const factura = this.props.facturas.facturas[index]
                    return factura.save()
                }
            }
        }
    }
</script>
