import { zodResolver } from '@hookform/resolvers/zod'
import { groupBy } from 'lodash'
import { SubmitHandler, useForm } from 'react-hook-form'
import { toast } from 'sonner'
import {
  Button,
  Card,
  CardContent,
  CardFooter,
  Form,
  FormControl,
  FormField,
  Input,
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from 'ui'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
import {
  PageSection,
  PageSectionContent,
  PageSectionMeta,
  PageSectionSummary,
  PageSectionTitle,
} from 'ui-patterns/PageSection'
import z from 'zod'

import { useProfileIdentitiesQuery } from '@/data/profile/profile-identities-query'
import { useProfileUpdateMutation } from '@/data/profile/profile-update-mutation'
import { useProfile } from '@/lib/profile'

const FormSchema = z.object({
  first_name: z.string().optional(),
  last_name: z.string().optional(),
  username: z.string().optional(),
  primary_email: z.string().email().optional(),
})

const formId = 'profile-information-form'

export const ProfileInformation = () => {
  const { profile } = useProfile()

  const {
    data: identityData,
    isPending: isIdentitiesLoading,
    isSuccess: isIdentitiesSuccess,
  } = useProfileIdentitiesQuery()
  const identities = (identityData?.identities ?? []).filter((x) => x.identity_data?.email !== null)
  const dedupedIdentityEmails = Object.keys(groupBy(identities, 'identity_data.email'))

  const defaultValues = {
    first_name: profile?.first_name ?? '',
    last_name: profile?.last_name ?? '',
    username: profile?.username ?? '',
    primary_email: profile?.primary_email ?? '',
  }

  const form = useForm({
    resolver: zodResolver(FormSchema as any),
    defaultValues,
    values: defaultValues,
  })

  const { mutate: updateProfile, isPending: isUpdatingProfile } = useProfileUpdateMutation({
    onSuccess: (data) => {
      toast.success('Successfully saved profile')
      const { first_name, last_name, username, primary_email } = data
      form.reset({
        first_name: first_name ?? undefined,
        last_name: last_name ?? undefined,
        username,
        primary_email,
      })
    },
    onError: (error) => toast.error(`Failed to update profile: ${error.message}`),
  })

  const onSubmit: SubmitHandler<z.infer<typeof FormSchema>> = async (data) => {
    updateProfile({
      firstName: data.first_name || '',
      lastName: data.last_name || '',
      username: data.username || '',
      primaryEmail: data.primary_email || '',
    })
  }

  return (
    <PageSection>
      <PageSectionMeta>
        <PageSectionSummary>
          <PageSectionTitle>Profile information</PageSectionTitle>
        </PageSectionSummary>
      </PageSectionMeta>
      <PageSectionContent>
        <Form {...form}>
          <form id={formId} className="space-y-6 w-full" onSubmit={form.handleSubmit(onSubmit)}>
            <Card>
              <CardContent>
                <FormField
                  control={form.control}
                  name="first_name"
                  render={({ field }) => (
                    <FormItemLayout label="First name" layout="flex-row-reverse">
                      <FormControl className="col-span-8">
                        <Input {...field} placeholder="First name" className="w-full" />
                      </FormControl>
                    </FormItemLayout>
                  )}
                />
              </CardContent>
              <CardContent>
                <FormField
                  control={form.control}
                  name="last_name"
                  render={({ field }) => (
                    <FormItemLayout label="Last name" layout="flex-row-reverse">
                      <FormControl className="col-span-8">
                        <Input {...field} placeholder="Last name" className="w-full" />
                      </FormControl>
                    </FormItemLayout>
                  )}
                />
              </CardContent>
              <CardContent>
                <FormField
                  control={form.control}
                  name="primary_email"
                  render={({ field }) => (
                    <FormItemLayout
                      label="Primary email"
                      description={
                        profile?.is_sso_user
                          ? 'Managed by your SSO provider and cannot be changed here'
                          : 'Used for account notifications'
                      }
                      layout="flex-row-reverse"
                    >
                      <FormControl className="col-span-8">
                        <div className="flex flex-col gap-1">
                          <Select
                            value={field.value}
                            onValueChange={field.onChange}
                            disabled={profile?.is_sso_user}
                          >
                            <SelectTrigger className="col-span-8 w-full">
                              <SelectValue placeholder="Select primary email" />
                            </SelectTrigger>
                            <SelectContent className="col-span-8">
                              {isIdentitiesSuccess &&
                                dedupedIdentityEmails.map((email) => (
                                  <SelectItem key={email} value={email}>
                                    {email}
                                  </SelectItem>
                                ))}
                            </SelectContent>
                          </Select>
                        </div>
                      </FormControl>
                    </FormItemLayout>
                  )}
                />
              </CardContent>
              <CardContent>
                <FormField
                  control={form.control}
                  name="username"
                  render={({ field }) => (
                    <FormItemLayout
                      label="Username"
                      description={
                        profile?.is_sso_user
                          ? 'Managed by your SSO provider and cannot be changed here'
                          : 'Display name used across dashboard'
                      }
                      layout="flex-row-reverse"
                    >
                      <FormControl className="col-span-8">
                        <div className="flex flex-col gap-1">
                          <Input
                            {...field}
                            className="w-full"
                            placeholder="Username"
                            disabled={profile?.is_sso_user}
                          />
                        </div>
                      </FormControl>
                    </FormItemLayout>
                  )}
                />
              </CardContent>
              <CardFooter className="justify-end space-x-2">
                {form.formState.isDirty && (
                  <Button type="default" onClick={() => form.reset()}>
                    Cancel
                  </Button>
                )}
                <Button
                  type="primary"
                  htmlType="submit"
                  loading={isUpdatingProfile || isIdentitiesLoading}
                  disabled={!form.formState.isDirty}
                >
                  Save
                </Button>
              </CardFooter>
            </Card>
          </form>
        </Form>
      </PageSectionContent>
    </PageSection>
  )
}
