import { defineComponent, onMounted, ref } from 'vue'
import { GranulatsMarinsActivite } from './granulats-marins-activite'
import { ConfigurableChart } from '../_charts/configurable-chart'
import { StatistiqueGranulatsMarinsStatAnnee, StatistiquesGranulatsMarins } from 'camino-common/src/statistiques.js'
import { AsyncData, getWithJson } from '@/api/client-rest'
import { LoadingElement } from '../_ui/functional-loader'
import { anneePrecedente, CaminoAnnee, CaminoDate, getAnnee, getCurrent, toCaminoAnnee, toCaminoDate } from 'camino-common/src/date'
import type { ChartConfiguration } from 'chart.js'
import { numberFormat } from 'camino-common/src/number'
import styles from './statistiques.module.css'
import { DsfrSelect } from '../_ui/dsfr-select'
import { isNonEmptyArray, map } from 'camino-common/src/typescript-tools'
import { DsfrSeparator } from '../_ui/dsfr-separator'
import { CHART_COLORS } from '../_charts/utils'

const ids = ['titresPrw', 'titresPxw', 'titresCxw', 'concessionsValides'] as const

const suggestedMaxCalc = (annees: StatistiqueGranulatsMarinsStatAnnee[]) =>
  Math.max(
    ...annees.reduce<number[]>((acc, annee) => {
      acc.push(...ids.map(id => annee[id].quantite))

      return acc
    }, [])
  )

const statsBarFormat = ({
  annees,
  id,
  bar,
  line,
  labelBar,
  labelLine,
}: {
  annees: StatistiqueGranulatsMarinsStatAnnee[]
  id?: (typeof ids)[number]
  bar: 'volume' | 'quantite'
  line: 'masse' | 'surface'
  labelBar: string
  labelLine: string
}): ChartConfiguration<'bar' | 'line'>['data'] =>
  annees.reduce<{
    labels: CaminoAnnee[]
    datasets: {
      type: 'line' | 'bar'
      label: string
      yAxisID: 'line' | 'bar'
      fill?: 'start'
      tension?: number
      backgroundColor: string
      borderColor?: string
      data: number[]
    }[]
  }>(
    (acc, stats) => {
      acc.labels.push(stats.annee)
      const dataLine: number = line === 'surface' ? stats[id ?? 'concessionsValides'][line] : stats[line]
      const dataBar: number = bar === 'quantite' ? stats[id ?? 'concessionsValides'][bar] : stats[bar]
      acc.datasets[0].data.push(dataLine)
      acc.datasets[1].data.push(dataBar)

      return acc
    },
    {
      labels: [],
      datasets: [
        {
          type: 'line',
          label: labelLine,
          data: [],
          yAxisID: 'line',
          tension: 0.5,
          backgroundColor: CHART_COLORS.orange,
          borderColor: CHART_COLORS.orange,
        },
        {
          type: 'bar',
          label: labelBar,
          yAxisID: 'bar',
          data: [],
          backgroundColor: CHART_COLORS.blue,
        },
      ],
    }
  )

const getStats = async (): Promise<StatistiquesGranulatsMarins> => {
  const data: StatistiquesGranulatsMarins = await getWithJson('/rest/statistiques/granulatsMarins', {})

  return data
}

const barChartConfig = (data: ChartConfiguration<'bar' | 'line'>['data'], suggestedMax: number): ChartConfiguration<'bar' | 'line'> => ({
  type: 'bar',
  data,
  options: {
    locale: 'fr-FR',
    aspectRatio: 2,
    responsive: true,
    scales: {
      bar: { min: 0, position: 'left', suggestedMax },
      line: { min: 0, position: 'right' },
    },
    plugins: {
      legend: {
        reverse: true,
      },
    },
  },
})

export const GranulatsMarins = defineComponent({
  setup() {
    return () => <PureGranulatsMarins getStatistiques={getStats} />
  },
})

interface Props {
  currentDate?: CaminoDate
  getStatistiques: () => Promise<StatistiquesGranulatsMarins>
}
export const PureGranulatsMarins = defineComponent<Props>(props => {
  const statistiquesGranulatsMarins = ref<
    AsyncData<{
      raw: StatistiquesGranulatsMarins
      statistiques: Record<CaminoAnnee, StatistiqueGranulatsMarinsStatAnnee>
      statsAnneesAfter2010: StatistiqueGranulatsMarinsStatAnnee[]
    }>
  >({ status: 'LOADING' })
  const currentDate = props.currentDate ? props.currentDate : getCurrent()
  const anneeCurrent = getAnnee(currentDate)
  const anneeActive = ref<CaminoAnnee>(anneePrecedente(anneeCurrent))

  const anneeSelect = (annee: CaminoAnnee | null) => {
    if (annee !== null) {
      anneeActive.value = annee
    }
  }
  const suggestedMaxTitres = (titreType: (typeof ids)[number], annees: StatistiqueGranulatsMarinsStatAnnee[]) => {
    // si le nombre maximum de titres est inférieur à 10
    if (titreType && ids.includes(titreType) && Math.max(...annees.map(annee => annee[titreType].quantite)) <= 10) {
      return 10
    }

    return suggestedMaxCalc(annees)
  }

  onMounted(async () => {
    anneeActive.value = anneePrecedente(anneePrecedente(anneeCurrent))
    try {
      const data = await props.getStatistiques()

      const statistiques = data.annees.reduce<Record<string, any>>((acc, statsAnnee) => {
        acc[statsAnnee.annee] = statsAnnee

        return acc
      }, {})

      const statsAnneesAfter2010 = data.annees.filter(annee => annee.annee >= toCaminoAnnee(2010) && annee.annee < anneeCurrent)

      // affichage des données de l'année n-2 à partir du 1er avril de l'année en cours
      const toggleDate = toCaminoDate(`${anneeCurrent}-04-01`)
      const beforeToggleDate = currentDate < toggleDate

      statistiquesGranulatsMarins.value = {
        status: 'LOADED',
        value: {
          raw: data,
          statistiques,
          statsAnneesAfter2010: beforeToggleDate ? statsAnneesAfter2010.filter(annee => annee.annee < anneePrecedente(anneeCurrent)) : statsAnneesAfter2010,
        },
      }
    } catch (ex: any) {
      statistiquesGranulatsMarins.value = {
        status: 'ERROR',
        message: ex.message ?? 'something wrong happened',
      }
      console.error(ex)
    }
  })

  return () => (
    <>
      <div class="fr-container--fluid">
        <div id="etat">
          <h2>État du domaine minier en temps réel</h2>
          <span class="separator" />
          <p>
            Les données affichées ici sont celles contenues dans la base de donnée Camino. Elles sont susceptibles d’évoluer chaque jour au grès des décisions et de la fin de validité des titres et
            autorisations.
          </p>
          <p>
            Les surfaces cumulées concernées par un titre ou une autorisation n’impliquent pas qu’elles sont effectivement explorées ou exploitées sur tout ou partie de l'année. Les travaux miniers
            font l’objet de déclarations ou d’autorisations distinctes portant sur une partie seulement de la surface des titres miniers.
          </p>
          <div class="fr-mb-2w">
            <h3>Titres d'exploration</h3>
            <hr />
            <div class="fr-grid-row">
              <div class="fr-col-12 fr-col-md-4">
                <p class={['fr-display--xs', styles['donnee-importante']]}>
                  <LoadingElement data={statistiquesGranulatsMarins.value} renderItem={item => <>{item.raw.titresInstructionExploration}</>} />
                </p>

                <LoadingElement
                  data={statistiquesGranulatsMarins.value}
                  renderItem={item => {
                    if (item.raw.titresInstructionExploration > 1) {
                      return (
                        <div>
                          <p class="text-center">Demandes en cours d'instruction (initiale, modification en instance et survie provisoire)</p>
                        </div>
                      )
                    } else {
                      return (
                        <div>
                          <p class="text-center">Demande en cours d'instruction (initiale, modification en instance et survie provisoire)</p>
                        </div>
                      )
                    }
                  }}
                />
                <p class="h6 text-center">
                  <router-link
                    to={{
                      name: 'titres',
                      query: {
                        domainesIds: 'w',
                        typesIds: 'ar,ap,pr',
                        statutsIds: 'dmi,mod,sup',
                        vueId: 'table',
                      },
                    }}
                  >
                    Voir les titres
                  </router-link>
                </p>
              </div>
              <div class="fr-col-12 fr-col-md-4">
                <p class={['fr-display--xs', styles['donnee-importante']]}>
                  <LoadingElement data={statistiquesGranulatsMarins.value} renderItem={item => <>{item.raw.titresValPrw}</>} />
                </p>
                <p class="text-center">Permis exclusifs de recherches</p>
                <p class="h6 text-center">
                  <router-link
                    to={{
                      name: 'titres',
                      query: {
                        domainesIds: 'w',
                        typesIds: 'pr',
                        statutsIds: 'val',
                        vueId: 'table',
                      },
                    }}
                  >
                    Voir les titres
                  </router-link>
                </p>
              </div>
              <div class="fr-col-12 fr-col-md-4">
                <p class={['fr-display--xs', styles['donnee-importante']]}>
                  <LoadingElement data={statistiquesGranulatsMarins.value} renderItem={item => <>{numberFormat(item.raw.surfaceExploration)} ha</>} />
                </p>
                <p class="text-center">Surfaces cumulées des titres pouvant faire l'objet d'une activité d’exploration</p>
              </div>
            </div>
          </div>
          <div class="fr-mb-2w">
            <h3>Titres d’exploitation</h3>
            <hr />
            <div class="fr-grid-row">
              <div class="fr-col-12 fr-col-md-4">
                <p class={['fr-display--xs', styles['donnee-importante']]}>
                  <LoadingElement data={statistiquesGranulatsMarins.value} renderItem={item => <>{item.raw.titresInstructionExploitation}</>} />
                </p>
                <LoadingElement
                  data={statistiquesGranulatsMarins.value}
                  renderItem={item => {
                    if (item.raw.titresInstructionExploitation > 1) {
                      return (
                        <div>
                          <p class="text-center">Demandes en cours d'instruction (initiale, modification en instance et survie provisoire)</p>
                        </div>
                      )
                    } else {
                      return (
                        <div>
                          <p class="text-center">Demande en cours d'instruction (initiale, modification en instance et survie provisoire)</p>
                        </div>
                      )
                    }
                  }}
                />

                <p class="h6 text-center">
                  <router-link
                    to={{
                      name: 'titres',
                      query: {
                        domainesIds: 'w',
                        typesIds: 'ax,cx,px',
                        statutsIds: 'dmi,mod,sup',
                        vueId: 'table',
                      },
                    }}
                  >
                    Voir les titres
                  </router-link>
                </p>
              </div>
              <div class="fr-col-12 fr-col-md-4">
                <p class={['fr-display--xs', styles['donnee-importante']]}>
                  <LoadingElement data={statistiquesGranulatsMarins.value} renderItem={item => <>{item.raw.titresValCxw}</>} />
                </p>
                <LoadingElement
                  data={statistiquesGranulatsMarins.value}
                  renderItem={item => (
                    <div>
                      <p class="text-center">Concession{item.raw.titresValCxw > 1 ? 's' : ''}</p>
                    </div>
                  )}
                />

                <p class="h6 text-center">
                  <router-link
                    to={{
                      name: 'titres',
                      query: {
                        domainesIds: 'w',
                        typesIds: 'cx',
                        statutsIds: 'val',
                        vueId: 'table',
                      },
                    }}
                  >
                    Voir les titres
                  </router-link>
                </p>
              </div>
              <div class="fr-col-12 fr-col-md-4">
                <p class={['fr-display--xs', styles['donnee-importante']]}>
                  <LoadingElement data={statistiquesGranulatsMarins.value} renderItem={item => <>{numberFormat(item.raw.surfaceExploitation)} ha</>} />
                </p>
                <p class="text-center">Surfaces cumulées des titres pouvant faire l'objet d'une activité d’exploitation</p>
              </div>
            </div>
          </div>
        </div>

        <DsfrSeparator />

        <h2>Production annuelle</h2>
        <span class="separator" />
        <p class="fr-mb-3w">Données contenues dans la base de données Camino, stabilisées pour l’année n-1.</p>

        <div class="fr-pt-1w fr-pb-1w">
          <LoadingElement
            data={statistiquesGranulatsMarins.value}
            renderItem={({ statsAnneesAfter2010 }) => {
              return (
                <ConfigurableChart
                  chartConfiguration={barChartConfig(
                    statsBarFormat({
                      annees: statsAnneesAfter2010,
                      bar: 'volume',
                      line: 'masse',
                      labelBar: 'Volume en m³',
                      labelLine: 'Tonnage',
                    }),
                    Math.max(...statsAnneesAfter2010.map(annee => annee.volume))
                  )}
                  description="Production de granulats marins par année"
                  a11yDescription="autoyearlytable"
                />
              )
            }}
          />
        </div>

        <DsfrSeparator />

        <LoadingElement
          data={statistiquesGranulatsMarins.value}
          renderItem={item => {
            const annees = item.statsAnneesAfter2010.map(annee => {
              const id = annee.annee

              return {
                id,
                nom: id.toString(),
                enConstruction: id === anneePrecedente(anneeCurrent), // l'année en cours n'étant pas affichée, seule l'année précédente est affichée à partir du 1er avril de l'année courante
              }
            })

            if (isNonEmptyArray(annees)) {
              const anneesLabel = map(annees, annee => ({ id: annee.id, label: annee.nom }))
              return (
                <>
                  <DsfrSelect required={true} legend={{ main: 'Sélectionner une année' }} items={anneesLabel} initialValue={anneeActive.value} valueChanged={anneeSelect} />
                  <GranulatsMarinsActivite statistiqueGranulatsMarins={item.statistiques[anneeActive.value]} enConstruction={annees.find(t => t.id === anneeActive.value)?.enConstruction} />
                </>
              )
            } else {
              return null
            }
          }}
        />

        <DsfrSeparator />

        <div id="evolution" class="mb-xxl">
          <h2>Titres octroyés et surface</h2>
          <span class="separator" />
          <p>Données contenues dans la base de données Camino, concernant exclusivement le territoire français.</p>
          <h3>Permis exclusif de recherche (PER) octroyés</h3>
          <hr />
          <div class="fr-grid-row">
            <div class="fr-col-12 fr-col-md-3 fr-mb-3w mt">
              <p class={['fr-display--xs', styles['donnee-importante']]}>
                <LoadingElement data={statistiquesGranulatsMarins.value} renderItem={item => <>{item.statistiques[anneePrecedente(anneeCurrent)].titresPrw.quantite}</>} />
              </p>
              <p>Permis exclusifs de recherches octroyés l’an dernier</p>
            </div>
            <div class="fr-col-12 fr-col-md-9 relative fr-mb-3w">
              <LoadingElement
                data={statistiquesGranulatsMarins.value}
                renderItem={item => (
                  <ConfigurableChart
                    chartConfiguration={barChartConfig(
                      statsBarFormat({
                        annees: item.raw.annees,
                        id: 'titresPrw',
                        bar: 'quantite',
                        line: 'surface',
                        labelBar: 'Permis de recherches',
                        labelLine: 'Surface des permis de recherches (ha)',
                      }),
                      suggestedMaxTitres('titresPrw', item.raw.annees)
                    )}
                    description="Nombre de permis exclusifs de recherche par année"
                    a11yDescription="autoyearlytable"
                  />
                )}
              />
            </div>
          </div>
          <LoadingElement
            data={statistiquesGranulatsMarins.value}
            renderItem={({ statistiques, raw }) => {
              const statistiquesGranulatsMarinsAnneeCurrent = raw.annees.find(annee => annee.annee === anneeCurrent)
              const pexAnneeCurrent = (statistiquesGranulatsMarinsAnneeCurrent?.titresPxw?.quantite ?? 0) > 0

              return (
                <>
                  {pexAnneeCurrent ? (
                    <div>
                      <h3>Permis d'exploitation (PEX) octroyés</h3>
                      <hr />
                      <div class="fr-grid-row">
                        <div class="fr-col-12 fr-col-md-3 fr-mb-3w mt">
                          <p class={['fr-display--xs', styles['donnee-importante']]}>{statistiques[anneePrecedente(anneeCurrent)].titresPxw.quantite}</p>
                          <p>Permis d’exploitation octroyés l’an dernier</p>
                        </div>
                        <div class="fr-col-12 fr-col-md-9 relative fr-mb-3w">
                          <ConfigurableChart
                            chartConfiguration={barChartConfig(
                              statsBarFormat({
                                annees: raw.annees,
                                id: 'titresPxw',
                                bar: 'quantite',
                                line: 'surface',
                                labelBar: "Permis d'exploitation",
                                labelLine: "Surface des permis d'exploitation (ha)",
                              }),
                              suggestedMaxTitres('titresPxw', raw.annees)
                            )}
                            description="Nombre de permis d'exploitation par année"
                            a11yDescription="autoyearlytable"
                          />
                        </div>
                      </div>
                    </div>
                  ) : (
                    <div></div>
                  )}
                </>
              )
            }}
          />

          <h3>Concessions octroyées</h3>
          <hr />
          <div class="fr-grid-row">
            <div class="fr-col-12 fr-col-md-3 fr-mb-3w mt">
              <p class={['fr-display--xs', styles['donnee-importante']]}>
                <LoadingElement data={statistiquesGranulatsMarins.value} renderItem={item => <>{item.statistiques[anneePrecedente(anneeCurrent)].titresCxw.quantite}</>} />
              </p>
              <p>Concessions octroyées l’an dernier</p>
            </div>
            <div class="fr-col-12 fr-col-md-9 relative fr-mb-3w">
              <LoadingElement
                data={statistiquesGranulatsMarins.value}
                renderItem={item => (
                  <ConfigurableChart
                    chartConfiguration={barChartConfig(
                      statsBarFormat({
                        annees: item.raw.annees,
                        id: 'titresCxw',
                        bar: 'quantite',
                        line: 'surface',
                        labelBar: 'Concessions',
                        labelLine: 'Surfaces des concessions (ha)',
                      }),
                      suggestedMaxTitres('titresCxw', item.raw.annees)
                    )}
                    description="Nombre de concessions octroyées par année"
                    a11yDescription="autoyearlytable"
                  />
                )}
              />
            </div>
          </div>
          <h3>Concessions valides</h3>
          <hr />
          <div class="fr-grid-row">
            <div class="fr-col-12 fr-col-md-3 fr-mb-3w mt">
              <p class={['fr-display--xs', styles['donnee-importante']]}>
                <LoadingElement data={statistiquesGranulatsMarins.value} renderItem={item => <>{item.statistiques[anneePrecedente(anneeCurrent)].concessionsValides.quantite}</>} />
              </p>
              <p>Concessions valides l’an dernier</p>
            </div>
            <div class="fr-col-12 fr-col-md-9 relative fr-mb-3w">
              <LoadingElement
                data={statistiquesGranulatsMarins.value}
                renderItem={item => (
                  <ConfigurableChart
                    chartConfiguration={barChartConfig(
                      statsBarFormat({
                        annees: item.raw.annees,
                        id: 'concessionsValides',
                        bar: 'quantite',
                        line: 'surface',
                        labelBar: 'Concessions',
                        labelLine: 'Surfaces des concessions (ha)',
                      }),
                      suggestedMaxTitres('concessionsValides', item.raw.annees)
                    )}
                    description="Nombre de concessions valides par année"
                    a11yDescription="autoyearlytable"
                  />
                )}
              />
            </div>
          </div>
        </div>
      </div>
    </>
  )
})

// @ts-ignore waiting for https://github.com/vuejs/core/issues/7833
PureGranulatsMarins.props = ['currentDate', 'getStatistiques']
