import { MainLayout } from "@/layout/MainLayout/MainLayout";
import { cookies } from "next/headers";
import { db, JamTable, UserTable } from "@/lib/mastoauth/kysely";
import { ConditionalNull } from "@/components/utility/Conditional";
import Link from "next/link";
import Markdown from "react-markdown";
import rehypeRaw from "rehype-raw";
import { JSONContentTable, JSONJamTable, JSONJudgementTable, JSONUserTable } from "@/lib/mastoauth/realtypes";
import { notFound } from "next/navigation";

export default async function Home({
  params,
  searchParams
}: {
  params: {
    user: string
  },
  searchParams: { 
    jamuntil: string,
    conuntil: string,
    juduntil: string
  }
}) {
  const curDate = Date.now();
  const jamPage = parseInt(searchParams?.jamuntil) || curDate;
  const contentPage = parseInt(searchParams?.conuntil) || curDate;
  const judgementPage = parseInt(searchParams?.juduntil) || curDate;

  const cookieStore = cookies();
  const token = cookieStore.get('token')?.value;
  let existingUser;
  if (token != null) {
    let existingToken = await db
      .selectFrom('tokens')
      .where('tokens.id', '=', token)
      .select('owner')
      .executeTakeFirst();

    if (existingToken != null) {
      existingUser = await db
        .selectFrom('users')
        .where('users.id', '=', existingToken.owner)
        .selectAll()
        .executeTakeFirst();
    }
  }

  const curUser = params.user;

  if (curUser == null) return notFound();
  
  // It's a JSONJamTable. I don't know why TS hates `number` => `string` conversion.
  let user = await db
    .selectFrom('users')
    .where('users.id', '=', curUser)
    .selectAll()
    .executeTakeFirst() as unknown as JSONUserTable;

  if (user == null) return notFound();
  
  let content = await db
    .selectFrom('content')
    .where('content.author_id', '=', user.id)
    .where('content.submitted', '<=', contentPage)
    .limit(20)
    .orderBy('content.submitted', 'desc')
    .selectAll()
    .execute() as unknown[] as JSONContentTable[];
  
  let jams = await db
    .selectFrom('jams')
    .where('jams.author_id', '=', user.id)
    .where('jams.created', '<=', jamPage)
    .limit(20)
    .orderBy('jams.created', 'desc')
    .selectAll()
    .execute() as unknown[] as JSONJamTable[];
  
  let judgements = await db
    .selectFrom('judgements')
    .where('judgements.author_id', '=', user.id)
    .where('judgements.published', '<=', judgementPage)
    .limit(20)
    .orderBy('judgements.published', 'desc')
    .selectAll()
    .execute() as unknown[] as JSONJudgementTable[];

  return (
    <MainLayout currentPage="/jams/" title={`${user.username}@${user.instance}`} subtitle="Jams" backButton>
      <h1>{`${user.username}@${user.instance}`}</h1>
      <p><small>{user.banned ? <><b>BANNED</b> - </> : <></>}{user.admin ? <><b>ADMIN</b> - </> : <></>}Joined {new Date(parseInt(user.joined)).toDateString()}</small></p>
      <p><a href={user.url} target="_blank">{user.url}</a></p>
      <ConditionalNull condition={existingUser != null}>
        <div>
          <ConditionalNull condition={existingUser?.admin == true}><p><b>You have the ability to modify this user.</b></p></ConditionalNull>
          <ConditionalNull condition={existingUser?.admin == true}><p><a href={`/jams/edit/user/${user.id}`}>Edit user</a></p></ConditionalNull>
          <ConditionalNull condition={existingUser?.admin || existingUser?.id == user.id}><p><a href={`/jams/delete/user/${user.id}`}>Delete user</a></p></ConditionalNull>
        </div>
      </ConditionalNull>
      <ConditionalNull condition={jams.length > 0}>
        <h1>Jams</h1>
        {jams.map(async (jam:JSONJamTable) => {
          const started = Date.now() >= parseInt(jam.date_start);
          const ended = Date.now() >= parseInt(jam.date_end);
          
          let jamOwner = await db
            .selectFrom('users')
            .where('users.id', '=', jam.author_id)
            .selectAll()
            .executeTakeFirst();
          
          if (jamOwner == null) return <p>An error occured.</p>;

          return (<div style={{
            margin: "16px 0"
          }}>
            <h2><Link href={`/jams/jam/${jam.id}`}>{jam.name}</Link></h2>
            <p><small>{started ? "Started" : "Starts"} {new Date(parseInt(jam.date_start)).toDateString()} - {ended ? "Ended" : "Ends"} {new Date(parseInt(jam.date_end)).toDateString()}</small></p>
            <p>{jam.description}</p>
          </div>);
        })}
        <div className="navigation">
          <ConditionalNull condition={jamPage < curDate}>
            <Link href={`?`}>Later</Link>
          </ConditionalNull>
          <ConditionalNull condition={jams.length > 20}>
            <Link href={`?jamuntil=${parseInt(jams.at(-1)?.created || jamPage + "") - 1}`}>Earlier</Link>
          </ConditionalNull>
        </div>
      </ConditionalNull>
      <ConditionalNull condition={content.length > 0}>
        <h1>Submissions</h1>
        {content.map(async (content:JSONContentTable) => {
          let contentOwner = await db
            .selectFrom('users')
            .where('users.id', '=', content.author_id)
            .selectAll()
            .executeTakeFirst();
          
            if (contentOwner == null) return <p>An error occured.</p>;
    
          // It's a JSONJamTable. I don't know why TS hates `number` => `string` conversion.
          let submittedJam = await db
            .selectFrom('jams')
            .where('jams.id', '=', content.jam_id)
            .selectAll()
            .executeTakeFirst() as unknown as JSONJamTable;
          
          // if (submittedJam == null) return <p>An error occured.</p>;

          return (<div style={{
            margin: "16px 0"
          }}>
            <h2><Link href={`/jams/content/${content.id}`}>{content.name}</Link></h2>
            <ConditionalNull condition={submittedJam != null}> 
            <p><small>Submitted to <a href={`/jams/jam/${submittedJam?.id}?until=${content.submitted}`}>{submittedJam?.name}</a> - {new Date(parseInt(content.submitted)).toDateString()}</small></p>
            </ConditionalNull>
            <ConditionalNull condition={submittedJam == null}>
            <p><small>Submitted on {new Date(parseInt(content.submitted)).toDateString()} {content.winner && submittedJam != null && <>- <b>WINNER!</b></>}</small></p>
            </ConditionalNull>
            <p>{content.description}</p>
          </div>);
        })}
        <div className="navigation">
          <ConditionalNull condition={contentPage < curDate}>
            <Link href={`?`}>Later</Link>
          </ConditionalNull>
          <ConditionalNull condition={content.length > 20}>
            <Link href={`?conuntil=${parseInt(content.at(-1)?.submitted || contentPage + "") - 1}`}>Earlier</Link>
          </ConditionalNull>
        </div>
      </ConditionalNull>
      <ConditionalNull condition={judgements.length > 0}>
        <h1>Judgements</h1>
        {judgements.map(async (judgement:JSONJudgementTable) => {
          let judgementOwner = await db
            .selectFrom('users')
            .where('users.id', '=', judgement.author_id)
            .selectAll()
            .executeTakeFirst();
    
          // It's a JSONJamTable. I don't know why TS hates `number` => `string` conversion.
          let submittedContent = await db
            .selectFrom('content')
            .where('content.id', '=', judgement.content_id)
            .selectAll()
            .executeTakeFirst() as unknown as JSONContentTable;
          
          if (judgementOwner == null) return <p>An error occured.</p>;

          return (<div style={{
            margin: "16px 0"
          }}>
            <h2><a href={`/jams/content/${judgement.content_id}?until=${judgement.published}`}>{`${judgementOwner.username}@${judgementOwner.instance}`}</a></h2>
            <p><small>Published on {new Date(parseInt(judgement.published)).toDateString()} on <a href={`/jams/content/${submittedContent.id}?until=${judgement.published}`}>{submittedContent.name}</a></small></p>
            <p>{judgement.content}</p>
          </div>);
        })}
        <div className="navigation">
          <ConditionalNull condition={judgementPage < curDate}>
            <Link href={`?`}>Later</Link>
          </ConditionalNull>
          <ConditionalNull condition={judgements.length > 20}>
            <Link href={`?juduntil=${parseInt(judgements.at(-1)?.published || judgementPage + "") - 1}`}>Earlier</Link>
          </ConditionalNull>
        </div>
      </ConditionalNull>
    </MainLayout>
  )
}