@extends('layout.base')

@section('page_content')
    <div class="ui container">
        <h2 class="ui header">Matriz Facturación</h2>
        <h4 class="ui dividing header">
            <div class="ui two column grid">
                <div id="list_title" class="column">Proyectos</div>
                <div class="right aligned column">
                    <div class="ui tiny icon buttons">
                        <button id="up_button" class="ui button">
                            <i class="up arrow icon"></i>
                        </button>
                        <button id="refresh_button" class="ui button">
                            <i class="refresh icon"></i>
                        </button>
                    </div>
                </div>
            </div>
        </h4>
        <div id="proyectos" class="ui link selection list">
            @foreach ($proyectos as $proyecto)
                <div class="item" data-proyecto="{{$proyecto->id}}">{{$proyecto->descripcion}}</div>
            @endforeach
        </div>
    </div>
    <table class="ui table" id="data"></table>
@endsection

@include('layout.head.styles.datatables')
@include('layout.body.scripts.datatables')

@push('page_scripts')
    <script>
        const money = {
            ufs: {},
            ipcs: {},
            sent: {
                uf: {},
                ipc: {}
            },
            get() {
                return {
                    uf: date => {
                        if (typeof this.sent.uf[date.toISOString()] !== 'undefined') {
                            return this.sent.uf[date.toISOString()]
                        }
                        const url = '{{$urls->api}}/money/uf'
                        const data = new FormData()
                        data.set('fecha', date.toISOString())
                        const options = {
                            method: 'post',
                            body: data
                        }
                        return this.sent.uf[date.toISOString()] = fetchAPI(url, options).then(response => {
                            if (response.ok) {
                                return response.json()
                            }
                        }).then(json => {
                            return this.ufs[json.input.fecha] = json.uf
                        })
                    },
                    ipc: (end, start) => {
                        const dateKey = [start.getFullYear(), (start.getMonth()+1), end.getFullYear(), (end.getMonth()+1)].join('-')
                        if (typeof this.sent.ipc[dateKey] !== 'undefined') {
                            return this.sent.ipc[dateKey]
                        }
                        const url = '{{$urls->api}}/money/ipc'
                        const data = new FormData()
                        data.set('start', start.toISOString())
                        data.set('end', end.toISOString())
                        const options = {
                            method: 'post',
                            body: data
                        }
                        return this.sent.ipc[dateKey] = fetchAPI(url, options).then(response => {
                            if (response.ok) {
                                return response.json()
                            }
                        }).then(json => {
                            return this.ipcs[json.date_string] = json.ipc
                        })
                    }
                }
            }
        }

        class Unidad {
            id
            tipo
            descripcion
            prorrateo
            precio

            constructor({id, tipo, descripcion, prorrateo, precio})
            {
                this.id = id
                this.tipo = tipo
                this.descripcion = descripcion
                this.prorrateo = prorrateo
                this.precio = precio
            }
        }
        class Venta {
            id
            precio
            fecha
            escritura
            uf
            ipc
            unidades
            principal

            constructor({id, precio, fecha, escritura}) {
                this.id = id
                this.precio = precio
                this.fecha = fecha
                this.escritura = escritura
                this.uf = 1
                this.ipc = 1
                this.unidades = []
            }

            get() {
                return {
                    unidades: () => {
                        const url = '{{$urls->api}}/venta/' + this.id + '/unidades'
                        return fetchAPI(url).then(response => {
                            if (response.ok) {
                                return response.json()
                            }
                        }).then(json => {
                            json.unidades.forEach(unidad => {
                                const tipo = unidad.proyecto_tipo_unidad.tipo_unidad.descripcion
                                const data = {
                                    id: unidad.id,
                                    tipo: tipo.charAt(0).toUpperCase() + tipo.slice(1),
                                    descripcion: unidad.descripcion,
                                    prorrateo: unidad.prorrateo,
                                    precio: 0
                                }
                                if (unidad.current_precio !== null) {
                                    data.precio = unidad.current_precio.valor
                                }
                                const u = new Unidad(data)
                                this.unidades.push(u)
                            })
                            this.principal = this.unidades.filter(unidad => unidad.tipo === 'Departamento')[0]
                        })
                    }
                }
            }

            draw({tbody, valor_terreno}) {
                /**
                 'Venta',
                 'Unidades',
                 'Tipo',
                 'Unidad',
                 'Fecha Promesa',
                 'Valor Promesa',
                 'Prorrateo',
                 'Descuento',
                 'Precio Venta',
                 'Precio Bruto',
                 'IVA',
                 'Precio Neto',
                 '% IVA/Neto',
                 'Fecha Escritura',
                 'UF',
                 'IPC'
                 */
                const dateFormatter = new Intl.DateTimeFormat('es-CL', {year: 'numeric', month: 'numeric', day: 'numeric'})
                const pesosFormatter = new Intl.NumberFormat('es-CL', {style: 'currency', currency: 'CLP'})
                const ufFormatter = new Intl.NumberFormat('es-CL', {minimumFractionDigits: 2, maximumFractionDigits: 2})
                const venta = this.unidades[0].descripcion
                const cantidad = this.unidades.length
                this.unidades.forEach(unidad => {
                    const values = [
                        venta,
                        cantidad,
                        unidad.tipo,
                        unidad.descripcion,
                        dateFormatter.format(this.fecha),
                        ufFormatter.format(unidad.precio) + ' UF',
                        unidad.prorrateo,
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                        ''
                    ]
                    if (this.escritura !== null) {
                        const descuento = valor_terreno * (1 + this.ipc / 100) * unidad.prorrateo
                        const precio_venta = unidad.precio * this.uf
                        const precio_bruto = precio_venta - descuento
                        const precio_neto = precio_bruto / 1.19
                        const iva = precio_bruto - precio_neto

                        let i = 7
                        values[i++] = pesosFormatter.format(descuento)
                        values[i++] = pesosFormatter.format(precio_venta)
                        values[i++] = pesosFormatter.format(precio_bruto)
                        values[i++] = pesosFormatter.format(iva)
                        values[i++] = pesosFormatter.format(precio_neto)
                        values[i++] = (iva / precio_venta * 100).toFixed(2) + '%'
                        values[i++] = dateFormatter.format(this.escritura)
                        values[i++] = ufFormatter.format(this.uf)
                        values[i++] = (this.ipc).toFixed(2) + '%'
                    }
                    const row = $('<tr></tr>')
                    values.forEach(value => {
                        row.append(
                            $('<td></td>').html(value)
                        )
                    })
                    tbody.append(row)
                })
            }
        }
        const proyectos = {
            ids: {},
            selected: 0,
            data: JSON.parse('{!! json_encode($proyectos) !!}'),
            table: null,
            get: function() {
                return {
                    ventas: () => {
                        const url = '{{$urls->api}}/ventas/facturacion/proyecto/' + this.selected
                        return fetchAPI(url).then(response => {
                            if (response.ok) {
                                return response.json()
                            }
                        }).then(json => {
                            const idx = this.data.findIndex(proyecto => proyecto.id === json.proyecto_id)
                            const fecha_terreno = new Date(this.data[idx].terreno.date)
                            this.data[idx]['ventas'] = []
                            const ventas = []
                            json.ventas.forEach(venta => {
                                const data = {
                                    id: venta.id,
                                    precio: venta.valor,
                                    fecha: new Date(venta.fecha),
                                    escritura: null
                                }
                                if (['escriturando'].includes(venta.current_estado.tipo_estado_venta.descripcion)) {
                                    data.escritura = new Date(venta.current_estado.fecha)
                                }
                                const v = new Venta(data)
                                const promises = []
                                if (v.escritura !== null) {
                                    promises.push(money.get().uf(v.escritura).then(uf => {
                                        v.uf = uf
                                    }))
                                    promises.push(money.get().ipc(v.escritura, fecha_terreno).then(ipc => {
                                        v.ipc = ipc
                                    }))
                                }
                                promises.push(v.get().unidades())
                                const promise = Promise.all(promises).then(() => {
                                    this.data[idx].ventas.push(v)
                                })
                                ventas.push(promise)
                            })
                            Promise.all(ventas).then(() => {
                                this.data[idx].ventas.sort((a, b) => parseInt(a.principal.descripcion) - parseInt(b.principal.descripcion))
                                this.draw().ventas(idx)
                            })
                        })
                    }
                }
            },
            draw: function() {
                return {
                    proyectos: () => {
                        if (this.table !== null) {
                            this.table.clear()
                        }
                        $(this.ids.data).hide()
                        $(this.ids.proyectos).show()
                    },
                    ventas: proyecto_idx => {
                        const table = $(this.ids.data)
                        if (this.table !== null) {
                            this.table.clear().destroy()
                        }
                        table.append(this.draw().thead())
                        table.append(this.draw().tbody(proyecto_idx))
                        table.show()
                        $(this.ids.proyectos).hide()
                        if (this.table === null) {
                            this.table = table.DataTable()
                        }
                    },
                    thead: () => {
                        const thead = $('<thead></thead>')
                        const columns = [
                            'Venta',
                            'Unidades',
                            'Tipo',
                            'Unidad',
                            'Fecha Promesa',
                            'Valor Promesa',
                            'Prorrateo',
                            'Descuento',
                            'Precio Venta',
                            'Precio Bruto',
                            'IVA',
                            'Precio Neto',
                            '% IVA/Neto',
                            'Fecha Escritura',
                            'UF',
                            'IPC'
                        ]
                        const row = $('<tr></tr>')
                        columns.forEach(title => {
                            row.append(
                                $('<th></th>').html(title)
                            )
                        })
                        thead.append(row)
                        return thead
                    },
                    tbody: proyecto_idx => {
                        const tbody = $('<tbody></tbody>')
                        this.data[proyecto_idx].ventas.forEach(venta => {
                            venta.draw({tbody, valor_terreno: this.data[proyecto_idx].terreno.valor})
                        })
                        return tbody
                    }
                }
            },
            actions: function() {
                return {
                    up: event => {
                        this.draw().proyectos()
                    },
                    refresh: event => {
                        const list = $(this.ids.proyectos)
                        if (list.is(':hidden')) {
                            const table = $(this.ids.table)
                            table.hide()
                            if (this.table !== null) {
                                this.table.clear().destroy()
                                this.table = null
                            }
                            this.get().ventas()
                        } else {
                            this.draw().proyectos()
                        }
                    }
                }
            },
            setup: function({ids}) {
                this.ids = ids
                $(this.ids.data).hide()
                $(this.ids.proyectos).find('.item').click(event => {
                    this.selected = $(event.currentTarget).data('proyecto')
                    this.get().ventas()
                })

                $(this.ids.buttons.up).click(this.actions().up)
                $(this.ids.buttons.refresh).click(this.actions().refresh)
            }
        }
        $(document).ready(() => {
            proyectos.setup({ids: {
                    proyectos: '#proyectos',
                    data: '#data',
                    buttons: {
                        up: '#up_button',
                        refresh: '#refresh_button'
                    }
                }
            })
        })
    </script>
@endpush
