import { ApolloClient, InMemoryCache } from "@apollo/client";
import { prepareRoutes } from "@curi/router";
import { omit } from "ramda";
import React from "react";
import { ProjectDetail, ProjectEditor, PROJECT } from "./projects";
import { COMMIT_LIST_QUERY } from "./commons/graphql/queries";
import { CommitList } from "./commits/commit-list";
import { PipelineTaskDetail } from "./pipeline-tasks/pipeline-task-detail";
import { PipelineEditor } from "./pipelines/pipeline-editor";
import {
  CreatePipelineInput,
  CreateProjectInput,
  Pipeline,
  PipelineUnits,
  Project,
  WorkUnitInput,
} from "./generated/graphql";
import { PIPELINE } from "./pipelines";

export default prepareRoutes([
  {
    name: "dashboard",
    path: "",
    respond() {
      return { body: () => <div>DashBoard</div> };
    },
  }, // dashboard
  {
    name: "create-project",
    path: "projects/create",
    respond({ resolved }) {
      const input: CreateProjectInput = {
        name: "",
        comment: "",
        webHookSecret: "",
        sshUrl: "",
        webUrl: "",
      };
      return { body: () => <ProjectEditor project={input} /> };
    },
  }, // create-project
  {
    name: "edit-project",
    path: "projects/:projectId/edit",
    async resolve(
      matched,
      { client }: { client: ApolloClient<InMemoryCache> }
    ) {
      const { data } = await client.query<{ project: Project }>({
        query: PROJECT,
        variables: { id: matched?.params.projectId },
      });
      return {
        body: () => (
          <ProjectEditor project={omit(["__typename"], data.project)} />
        ),
      };
    },
    respond({ resolved }) {
      return resolved;
    },
  }, // edit-project
  {
    name: "create-pipeline",
    path: "projects/:projectId/pipelines/create",
    async resolve(
      matched,
      { client }: { client: ApolloClient<InMemoryCache> }
    ) {
      const units = [
        PipelineUnits.Checkout,
        PipelineUnits.InstallDependencies,
        PipelineUnits.Test,
        PipelineUnits.Deploy,
        PipelineUnits.CleanUp,
      ];
      const input: CreatePipelineInput = {
        name: "",
        branch: "",
        projectId: matched!.params.projectId,
        workUnitMetadata: {
          version: 1,
          units: units.map((util) => ({ type: util, scripts: [] })),
        },
      };
      return {
        body: () => <PipelineEditor pipeline={input as any} />,
      };
    },
    respond({ resolved }) {
      return resolved;
    },
  }, // create-pipeline
  {
    name: "edit-pipeline",
    path: "projects/:projectId/pipelines/:pipelineId/edit",
    async resolve(
      matched,
      { client }: { client: ApolloClient<InMemoryCache> }
    ) {
      const { data } = await client.query<{ pipeline: Pipeline }>({
        query: PIPELINE,
        variables: { id: matched?.params.pipelineId },
      });
      return {
        body: () => <PipelineEditor pipeline={data.pipeline} />,
      };
    },
    respond({ resolved }) {
      return resolved;
    },
  }, // edit-pipeline
  {
    name: "project-detail",
    path: "projects/:projectId",
    async resolve(
      matched,
      { client }: { client: ApolloClient<InMemoryCache> }
    ) {
      const { data } = await client.query<{ project: Project }>({
        query: PROJECT,
        variables: { id: matched?.params.projectId },
      });
      return {
        body: () => (
          <ProjectDetail project={omit(["__typename"], data.project)} />
        ),
      };
    },
    respond({ resolved }) {
      return resolved;
    },
    children: [
      {
        name: "pipeline-commits",
        path: "pipelines/:pipelineId/commits",
        async resolve(
          matched,
          { client }: { client: ApolloClient<InMemoryCache> }
        ) {
          const { data } = await client.query<{
            pipeline: Pipeline;
            project: Project;
          }>({
            query: COMMIT_LIST_QUERY,
            variables: {
              projectId: matched?.params.projectId,
              pipelineId: matched?.params.pipelineId,
            },
          });
          return {
            body: () => (
              <ProjectDetail project={omit(["__typename"], data.project)}>
                <CommitList pipeline={omit(["__typename"], data.pipeline)} />
              </ProjectDetail>
            ),
          };
        },
        respond({ resolved, error }) {
          return resolved || <div>Failed</div>;
        },
      }, // pipeline-commits
      {
        name: "pipeline-task-detail",
        path: "pipelines/:pipelineId/tasks/:taskId",
        async resolve(
          matched,
          { client }: { client: ApolloClient<InMemoryCache> }
        ) {
          const { data } = await client.query<{
            pipeline: Pipeline;
            project: Project;
          }>({
            query: COMMIT_LIST_QUERY,
            variables: {
              projectId: matched?.params.projectId,
              pipelineId: matched?.params.pipelineId,
            },
          });
          return {
            body: () => (
              <ProjectDetail project={omit(["__typename"], data.project)}>
                <PipelineTaskDetail taskId={matched?.params.taskId} />
              </ProjectDetail>
            ),
          };
        },
        respond({ resolved, error }) {
          return resolved || <div>Failed</div>;
        },
      }, // pipeline-task-detail
    ],
  }, // project-detail
]);
