import { siteConfig } from 'site/site.config.mjs'
import yaml from 'js-yaml'
// Hooks
import { useContext } from 'react'
import { useTranslation } from 'next-i18next'
import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useBugsnag } from 'shared/hooks/use-bugsnag.mjs'
// Context
import { ModalContext } from 'shared/context/modal-context.mjs'
// Components
import { ModalWrapper } from 'shared/components/wrappers/modal.mjs'
import { ChoiceButton } from 'shared/components/choice-button.mjs'
import { CopyToClipboard } from 'shared/components/copy-to-clipboard.mjs'
import { WebLink } from 'shared/components/link.mjs'
import { Spinner } from 'shared/components/spinner.mjs'

export const ns = ['errors']

const ReportId = ({ id, t }) => (
  <>
    <p>{t('leadId')}:</p>
    <div className="bg-primary rounded-lg border border-primary border-solid bg-opacity-10">
      <div
        className={`
        flex flex-row justify-between items-center
        text-sm font-medium text-primary
        p-4
      `}
      >
        <span>{id}</span>
        <CopyToClipboard content={id} />
      </div>
    </div>
  </>
)

const userInfo = (account) => `
## About the user

This report was submitted by <a href="https://freesewing.org/users/${account.id}">FreeSewing user #${account.id}</a>
with username **${account.username}**.`

const patronInfo = (account) =>
  account.patron
    ? `
## :purple_heart: This was reported by a FreeSewing patron

> Please prioritize this issue as well as other issues by patrons as they are.

`
    : `

## :snail: This was not reported by a FreeSewing patron

> With limited time and resources available, please prioritize issues from patrons instead.

`

const issueTemplate = ({ isPublic, account, data, bug = { id: 'unknown', url: '#' } }) => `
${patronInfo(account)}

- **Site**: ${siteConfig.site}
- **Public report**: ${isPublic ? 'Yes' : 'No'}
- **Bugsnag Context ID**: [${bug.id}](${bug.url})

Please refer to [the Bugsnag report](${bug.url}) for in-depth data and stack trace.
However, please note that this is not publicly available.

${isPublic ? userInfo(account) : ''}

## Data included in this issue

\`\`\`yaml
${yaml.dump(data)}
\`\`\`
`

const ModalSpinner = ({ t }) => (
  <ModalWrapper>
    <div className="w-full max-w-md text-center">
      <h2>{t('pleaseWait')}</h2>
      <Spinner className="w-24 h-24 text-secondary animate-spin m-auto" />
    </div>
  </ModalWrapper>
)

const ModalResult = ({ t, bug, issue, clearModal }) => (
  <ModalWrapper>
    <h2>{t('reportCreated')}</h2>
    <ReportId id={bug.id} t={t} />
    {issue ? (
      <>
        <p>{t('leadIssue')}</p>
        <WebLink href={issue.url} txt={`github.com/freesewing/freesewing/issues/${issue.nr}`} />
      </>
    ) : null}
    <p>
      <button className="btn btn-neutral mt-4" onClick={clearModal}>
        {t('close')}
      </button>
    </p>
  </ModalWrapper>
)

export const ModalProblemReport = ({ title, data }) => {
  // Hooks
  const { t } = useTranslation(ns)
  const reportError = useBugsnag()
  const { account } = useAccount()
  const backend = useBackend()

  // Context
  const { clearModal, setModal } = useContext(ModalContext)

  // Helper method to create an issue
  const createIssue = async ({ title, body, labels }) => {
    let result
    try {
      result = await backend.createIssue({ title, body, labels })
    } catch (err) {
      console.log(err)
    }

    if (result.success && result.data.issue)
      return { url: result.data.issue.html_url, nr: result.data.issue.number }

    return false
  }

  // Helper method for private error report
  const reportPrivate = async (evt) => {
    evt.stopPropagation()
    setModal(<ModalSpinner t={t} />)
    const error = new Error(`[private] ${title}`)
    const bug = await reportError(error, {
      ...data,
      private: true,
      public: false,
      patron: account.patron,
    })
    let issue = false
    if (account.patron) {
      const issueData = {
        title,
        body: issueTemplate({ isPublic: false, account, title, data, bug }),
        labels: ['problem-report', 'public-report', 'impacts-patron'],
      }
      issue = await createIssue(issueData)
    }
    setModal(<ModalResult {...{ bug, issue, t, clearModal }} />)
  }

  // Helper method for public error report
  const reportPublic = async (evt) => {
    evt.stopPropagation()
    setModal(<ModalSpinner t={t} />)
    const error = new Error(`[public] ${title}`)
    const bug = await reportError(error, {
      ...data,
      private: false,
      public: true,
      patron: account.patron,
    })
    const issueData = {
      title,
      body: issueTemplate({ isPublic: true, account, title, data, bug }),
      labels: ['problem-report', 'public-report'],
    }
    if (account.patron) issueData.labels.push('impacts-patron')
    const issue = await createIssue(issueData)
    setModal(<ModalResult {...{ bug, issue, t, clearModal }} />)
  }

  return (
    <ModalWrapper>
      <div className="grid gap-2 p-4 grid-cols-1 max-w-lg w-full">
        <h2>{t('errors:newReport')}</h2>
        <ChoiceButton title={t('privateReport.t')} onClick={reportPrivate}>
          <p>{t('privateReport.d')}</p>
        </ChoiceButton>
        <ChoiceButton title={t('publicReport.t')} onClick={reportPublic}>
          <p>{t('publicReport.d')}</p>
        </ChoiceButton>
        <button className="btn btn-neutral mt-4" onClick={clearModal}>
          {t('cancel')}
        </button>
      </div>
    </ModalWrapper>
  )
}