import React, { useState } from 'react'
import { RefreshIcon } from '@heroicons/react/outline'

import { AddFundsButton } from 'web/components/add-funds-button'
import { Page } from 'web/components/page'
import { SEO } from 'web/components/SEO'
import { Title } from 'web/components/title'
import { formatMoney } from 'common/util/format'
import { cleanDisplayName, cleanUsername } from 'common/util/clean-username'
import { changeUserInfo } from 'web/lib/firebase/api'
import { uploadImage } from 'web/lib/firebase/storage'
import { Col } from 'web/components/layout/col'
import { Row } from 'web/components/layout/row'
import { User, PrivateUser } from 'common/user'
import { getUserAndPrivateUser, updateUser } from 'web/lib/firebase/users'
import { defaultBannerUrl } from 'web/components/user-page'
import { SiteLink } from 'web/components/site-link'
import Textarea from 'react-expanding-textarea'
import { redirectIfLoggedOut } from 'web/lib/firebase/server-auth'
import { generateNewApiKey } from 'web/lib/api/api-key'
import { TwitchPanel } from 'web/components/profile/twitch-panel'

export const getServerSideProps = redirectIfLoggedOut('/', async (_, creds) => {
  return { props: { auth: await getUserAndPrivateUser(creds.uid) } }
})

function EditUserField(props: {
  user: User
  field: 'bio' | 'website' | 'bannerUrl' | 'twitterHandle' | 'discordHandle'
  label: string
}) {
  const { user, field, label } = props
  const [value, setValue] = useState(user[field] ?? '')

  async function updateField() {
    // Note: We trim whitespace before uploading to Firestore
    await updateUser(user.id, { [field]: value.trim() })
  }

  return (
    <div>
      <label className="label">{label}</label>

      {field === 'bio' ? (
        <Textarea
          className="textarea textarea-bordered w-full resize-none"
          value={value}
          onChange={(e) => setValue(e.target.value)}
          onBlur={updateField}
        />
      ) : (
        <input
          type="text"
          className="input input-bordered"
          value={value}
          onChange={(e) => setValue(e.target.value || '')}
          onBlur={updateField}
        />
      )}
    </div>
  )
}

export default function ProfilePage(props: {
  auth: { user: User; privateUser: PrivateUser }
}) {
  const { user, privateUser } = props.auth
  const [avatarUrl, setAvatarUrl] = useState(user.avatarUrl || '')
  const [avatarLoading, setAvatarLoading] = useState(false)
  const [name, setName] = useState(user.name)
  const [username, setUsername] = useState(user.username)
  const [apiKey, setApiKey] = useState(privateUser.apiKey || '')

  const updateDisplayName = async () => {
    const newName = cleanDisplayName(name)
    if (newName) {
      setName(newName)
      await changeUserInfo({ name: newName }).catch((_) => setName(user.name))
    } else {
      setName(user.name)
    }
  }

  const updateUsername = async () => {
    const newUsername = cleanUsername(username)
    if (newUsername) {
      setUsername(newUsername)
      await changeUserInfo({ username: newUsername }).catch((_) =>
        setUsername(user.username)
      )
    } else {
      setUsername(user.username)
    }
  }

  const updateApiKey = async (e: React.MouseEvent) => {
    const newApiKey = await generateNewApiKey(user.id)
    setApiKey(newApiKey ?? '')
    e.preventDefault()
  }

  const fileHandler = async (event: any) => {
    const file = event.target.files[0]

    setAvatarLoading(true)

    await uploadImage(user.username, file)
      .then(async (url) => {
        await changeUserInfo({ avatarUrl: url })
        setAvatarUrl(url)
        setAvatarLoading(false)
      })
      .catch(() => {
        setAvatarLoading(false)
        setAvatarUrl(user.avatarUrl || '')
      })
  }

  return (
    <Page>
      <SEO title="Profile" description="User profile settings" url="/profile" />

      <Col className="max-w-lg rounded bg-white p-6 shadow-md sm:mx-auto">
        <Row className="justify-between">
          <Title className="!mt-0" text="Edit Profile" />
          <SiteLink className="btn btn-primary" href={`/${user.username}`}>
            Done
          </SiteLink>
        </Row>
        <Col className="gap-4">
          <Row className="items-center gap-4">
            {avatarLoading ? (
              <button className="btn btn-ghost btn-lg btn-circle loading"></button>
            ) : (
              <>
                <img
                  src={avatarUrl}
                  width={80}
                  height={80}
                  className="flex items-center justify-center rounded-full bg-gray-400"
                />
                <input type="file" name="file" onChange={fileHandler} />
              </>
            )}
          </Row>

          <div>
            <label className="label">Display name</label>
            <input
              type="text"
              placeholder="Display name"
              className="input input-bordered"
              value={name}
              onChange={(e) => setName(e.target.value || '')}
              onBlur={updateDisplayName}
            />
          </div>

          <div>
            <label className="label">Username</label>
            <input
              type="text"
              placeholder="Username"
              className="input input-bordered"
              value={username}
              onChange={(e) => setUsername(e.target.value || '')}
              onBlur={updateUsername}
            />
          </div>

          {/* TODO: Allow users with M$ 2000 of assets to set custom banners */}
          {/* <EditUserField
                user={user}
                field="bannerUrl"
                label="Banner Url"
                isEditing={isEditing}
              /> */}
          <label className="label">
            Banner image{' '}
            <span className="text-sm text-gray-400">Not editable for now</span>
          </label>
          <div
            className="h-32 w-full bg-cover bg-center sm:h-40"
            style={{
              backgroundImage: `url(${
                user.bannerUrl || defaultBannerUrl(user.id)
              })`,
            }}
          />

          {(
            [
              ['bio', 'Bio'],
              ['website', 'Website URL'],
              ['twitterHandle', 'Twitter'],
              ['discordHandle', 'Discord'],
            ] as const
          ).map(([field, label]) => (
            <EditUserField
              key={field}
              user={user}
              field={field}
              label={label}
            />
          ))}

          <div>
            <label className="label">Email</label>
            <div className="ml-1 text-gray-500">
              {privateUser.email ?? '\u00a0'}
            </div>
          </div>

          <div>
            <label className="label">Balance</label>
            <Row className="ml-1 items-start gap-4 text-gray-500">
              {formatMoney(user.balance)}
              <AddFundsButton />
            </Row>
          </div>

          <div>
            <label className="label">API key</label>
            <div className="input-group w-full">
              <input
                type="text"
                placeholder="Click refresh to generate key"
                className="input input-bordered w-full"
                value={apiKey}
                readOnly
              />
              <button
                className="btn btn-primary btn-square p-2"
                onClick={updateApiKey}
              >
                <RefreshIcon />
              </button>
            </div>
          </div>

          <TwitchPanel />
        </Col>
      </Col>
    </Page>
  )
}