import {
  ClockCircleOutlined,
  DeploymentUnitOutlined,
  OrderedListOutlined,
  ReloadOutlined,
  ShoppingCartOutlined,
  SyncOutlined
} from '@ant-design/icons';
import {
  Alert,
  Button,
  Card,
  Descriptions,
  Empty,
  Form,
  Input,
  InputNumber,
  Layout,
  List,
  Menu,
  Result,
  Space,
  Spin,
  Table,
  Tag,
  Typography
} from 'antd';
import { type ReactNode, useMemo, useState } from 'react';
import { BrowserRouter, Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom';
import { ApiError } from './api/client';
import type { IdentityProvider } from './api/sessionApi';
import { SessionProvider, useSessionContext } from './auth/sessionContext';
import { buildGoogleOidcStartUrl } from './auth/oidcLogin';
import {
  loadDashboard,
  loadRecentActivity,
  submitFloorOrder,
  updateFloorOrder,
  type SubmitFloorOrderRequest,
  type SubmitFloorOrderResponse,
  type UpdateFloorOrderRequest,
  type UpdateFloorOrderResponse,
  type WaiterAssignmentsResponse,
  type WaiterRecentActivityResponse
} from './api/dashboardApi';

type AppRoute = '/assignments' | '/orders' | '/session';
type OrderEvent =
  | { kind: 'submitted'; response: SubmitFloorOrderResponse }
  | { kind: 'updated'; response: UpdateFloorOrderResponse };

type WorkflowState = {
  error: string | null;
  sessionExpired: boolean;
};

const routeItems: Array<{ key: AppRoute; label: string; icon: ReactNode }> = [
  { key: '/assignments', label: 'Assignments', icon: <OrderedListOutlined /> },
  { key: '/orders', label: 'Order Actions', icon: <ShoppingCartOutlined /> },
  { key: '/session', label: 'Session', icon: <DeploymentUnitOutlined /> }
];

const assignmentColumns = [
  { title: 'Waiter Id', dataIndex: 'waiterId' },
  { title: 'Table Id', dataIndex: 'tableId' },
  {
    title: 'Status',
    dataIndex: 'status',
    render: (value: string) => <Tag color={workflowTagColor(value)}>{value}</Tag>
  },
  { title: 'Active Orders', dataIndex: 'activeOrders' }
];

function App() {
  return (
    <SessionProvider>
      <BrowserRouter>
        <WaiterFloorShell />
      </BrowserRouter>
    </SessionProvider>
  );
}

function WaiterFloorShell() {
  const session = useSessionContext();
  const location = useLocation();
  const navigate = useNavigate();

  const [contextId, setContextId] = useState('demo-context');
  const [assignments, setAssignments] = useState<WaiterAssignmentsResponse | null>(null);
  const [recentActivity, setRecentActivity] = useState<WaiterRecentActivityResponse | null>(null);
  const [lastOrderResponse, setLastOrderResponse] = useState<SubmitFloorOrderResponse | UpdateFloorOrderResponse | null>(null);
  const [orderHistory, setOrderHistory] = useState<OrderEvent[]>([]);
  const [workflowState, setWorkflowState] = useState<WorkflowState>({ error: null, sessionExpired: false });
  const [loadingAssignments, setLoadingAssignments] = useState(false);
  const [submittingOrder, setSubmittingOrder] = useState(false);
  const [updatingOrder, setUpdatingOrder] = useState(false);

  const loginUrl = useMemo(() => buildGoogleOidcStartUrl(window.location.href), []);
  const selectedKey = useMemo(() => {
    const candidate = routeItems.find((item) => location.pathname.startsWith(item.key));
    return candidate?.key ?? '/assignments';
  }, [location.pathname]);

  const clearWorkflowError = () => setWorkflowState({ error: null, sessionExpired: false });

  const handleWorkflowFailure = async (err: unknown, fallbackMessage: string) => {
    if (err instanceof ApiError && err.status === 401) {
      setWorkflowState({ error: 'Your session expired. Sign in again to continue floor operations.', sessionExpired: true });
      await session.revalidate();
      return;
    }

    setWorkflowState({
      error: err instanceof Error ? err.message : fallbackMessage,
      sessionExpired: false
    });
  };

  const loadAssignments = async () => {
    setLoadingAssignments(true);
    clearWorkflowError();
    try {
      const [assignmentsPayload, activityPayload] = await Promise.all([
        loadDashboard(contextId),
        loadRecentActivity(contextId)
      ]);
      setAssignments(assignmentsPayload);
      setRecentActivity(activityPayload);
    } catch (err) {
      await handleWorkflowFailure(err, 'Failed to load waiter assignments.');
    } finally {
      setLoadingAssignments(false);
    }
  };

  const submitOrder = async (request: SubmitFloorOrderRequest) => {
    setSubmittingOrder(true);
    clearWorkflowError();
    try {
      const payload = await submitFloorOrder(request);
      setLastOrderResponse(payload);
      setOrderHistory((previous) => [{ kind: 'submitted' as const, response: payload }, ...previous].slice(0, 8));
    } catch (err) {
      await handleWorkflowFailure(err, 'Failed to submit floor order.');
    } finally {
      setSubmittingOrder(false);
    }
  };

  const reviseOrder = async (request: UpdateFloorOrderRequest) => {
    setUpdatingOrder(true);
    clearWorkflowError();
    try {
      const payload = await updateFloorOrder(request);
      setLastOrderResponse(payload);
      setOrderHistory((previous) => [{ kind: 'updated' as const, response: payload }, ...previous].slice(0, 8));
    } catch (err) {
      await handleWorkflowFailure(err, 'Failed to update floor order.');
    } finally {
      setUpdatingOrder(false);
    }
  };

  if (session.status === 'loading') {
    return (
      <div className="fullscreen-center">
        <Spin size="large" />
      </div>
    );
  }

  if (session.status !== 'authenticated' || !session.profile) {
    return (
      <main className="app">
        <Result
          status="403"
          title="Authentication Required"
          subTitle="Sign in through the central auth host to access waiter-floor operations."
          extra={
            <Button type="primary" href={loginUrl}>
              Continue with Google
            </Button>
          }
        />
        {session.error && <Alert type="error" showIcon message={session.error} />}
        {workflowState.sessionExpired && (
          <Alert
            className="stack-gap"
            type="warning"
            showIcon
            message="Session expired"
            description="Your last workflow action returned 401, so the app is asking you to sign in again."
          />
        )}
      </main>
    );
  }

  return (
    <Layout className="full-layout">
      <Layout.Sider width={240} breakpoint="lg" collapsedWidth={0}>
        <div className="brand">Waiter Floor Web</div>
        <Menu
          mode="inline"
          selectedKeys={[selectedKey]}
          items={routeItems}
          onClick={(event) => navigate(event.key as AppRoute)}
        />
      </Layout.Sider>
      <Layout>
        <Layout.Header className="header">
          <Space wrap>
            <Tag color="blue">subject: {session.profile.subjectId}</Tag>
            <Tag color="geekblue">tenant: {session.profile.tenantId}</Tag>
            <Tag color="purple">provider: {providerLabel(session.profile.provider)}</Tag>
          </Space>
          <Space>
            <Button icon={<ReloadOutlined />} onClick={() => void session.refresh()}>
              Refresh Session
            </Button>
            <Button danger onClick={() => void session.logout()}>
              Logout
            </Button>
          </Space>
        </Layout.Header>
        <Layout.Content className="content">
          <Typography.Title level={3}>Waiter Floor Operations</Typography.Title>
          <Typography.Paragraph type="secondary">
            Protected floor workflows for assignment visibility, recent activity, and order actions that now feed the same restaurant lifecycle used by kitchen and POS.
          </Typography.Paragraph>
          {session.error && <Alert className="stack-gap" type="warning" showIcon message={session.error} />}
          {workflowState.error && (
            <Alert
              className="stack-gap"
              type={workflowState.sessionExpired ? 'warning' : 'error'}
              showIcon
              message={workflowState.error}
              action={
                workflowState.sessionExpired ? (
                  <Button size="small" type="primary" href={loginUrl}>
                    Reauthenticate
                  </Button>
                ) : undefined
              }
            />
          )}

          <Routes>
            <Route
              path="/assignments"
              element={
                <Space direction="vertical" size="middle" style={{ width: '100%' }}>
                  <Card title="Assignments Snapshot">
                    <Space direction="vertical" size="middle" style={{ width: '100%' }}>
                      <Space wrap>
                        <Input
                          value={contextId}
                          onChange={(event) => setContextId(event.target.value)}
                          placeholder="Context Id"
                          style={{ width: 280 }}
                        />
                        <Button type="primary" loading={loadingAssignments} onClick={() => void loadAssignments()}>
                          Load Assignments
                        </Button>
                        <Button icon={<SyncOutlined />} onClick={() => void loadAssignments()} disabled={loadingAssignments}>
                          Retry
                        </Button>
                      </Space>
                      {assignments ? (
                        <>
                          <Descriptions bordered size="small" column={1}>
                            <Descriptions.Item label="Context Id">{assignments.contextId}</Descriptions.Item>
                            <Descriptions.Item label="Location Id">{assignments.locationId}</Descriptions.Item>
                            <Descriptions.Item label="Summary">{assignments.summary}</Descriptions.Item>
                            <Descriptions.Item label="Lifecycle Note">
                              Floor actions create or update shared restaurant orders that kitchen and POS observe next.
                            </Descriptions.Item>
                          </Descriptions>
                          <Table
                            pagination={false}
                            rowKey={(record) => `${record.waiterId}-${record.tableId}`}
                            dataSource={assignments.assignments}
                            columns={assignmentColumns}
                            locale={{ emptyText: 'No active waiter assignments for this context.' }}
                          />
                        </>
                      ) : (
                        <Empty description="Load a context to review assignment coverage." />
                      )}
                    </Space>
                  </Card>
                  <Card title="Recent Activity" extra={<ClockCircleOutlined />}>
                    {recentActivity && recentActivity.recentActivity.length > 0 ? (
                      <List
                        bordered
                        dataSource={recentActivity.recentActivity}
                        renderItem={(item) => <List.Item>{item}</List.Item>}
                      />
                    ) : (
                      <Empty description="No activity loaded yet. Load assignments first to refresh this feed." />
                    )}
                  </Card>
                </Space>
              }
            />
            <Route
              path="/orders"
              element={
                <Space direction="vertical" size="middle" style={{ width: '100%' }}>
                  <Card title="Submit Floor Order">
                    <Typography.Paragraph type="secondary">
                      New floor orders are accepted into the shared restaurant lifecycle first, then they progress through kitchen preparation and payment readiness.
                    </Typography.Paragraph>
                    <Form
                      layout="vertical"
                      initialValues={{
                        contextId,
                        tableId: 'T-12',
                        orderId: 'ORD-1001',
                        itemCount: 3
                      }}
                      onFinish={(values: SubmitFloorOrderRequest) => void submitOrder(values)}
                    >
                      <Form.Item name="contextId" label="Context Id" rules={[{ required: true }]}>
                        <Input placeholder="Context Id" />
                      </Form.Item>
                      <Form.Item name="tableId" label="Table Id" rules={[{ required: true }]}>
                        <Input placeholder="Table Id" />
                      </Form.Item>
                      <Form.Item name="orderId" label="Order Id" rules={[{ required: true }]}>
                        <Input placeholder="Order Id" />
                      </Form.Item>
                      <Form.Item name="itemCount" label="Item Count" rules={[{ required: true, type: 'number', min: 1 }]}>
                        <InputNumber min={1} style={{ width: '100%' }} />
                      </Form.Item>
                      <Button type="primary" htmlType="submit" loading={submittingOrder}>
                        Submit Floor Order
                      </Button>
                    </Form>
                  </Card>
                  <Card title="Update Existing Order">
                    <Typography.Paragraph type="secondary">
                      Updates keep the same shared order identity so the downstream kitchen and POS views stay consistent.
                    </Typography.Paragraph>
                    <Form
                      layout="vertical"
                      initialValues={{
                        contextId,
                        tableId: 'T-12',
                        orderId: 'ORD-1001',
                        itemCount: 4
                      }}
                      onFinish={(values: UpdateFloorOrderRequest) => void reviseOrder(values)}
                    >
                      <Form.Item name="contextId" label="Context Id" rules={[{ required: true }]}>
                        <Input placeholder="Context Id" />
                      </Form.Item>
                      <Form.Item name="tableId" label="Table Id" rules={[{ required: true }]}>
                        <Input placeholder="Table Id" />
                      </Form.Item>
                      <Form.Item name="orderId" label="Order Id" rules={[{ required: true }]}>
                        <Input placeholder="Order Id" />
                      </Form.Item>
                      <Form.Item name="itemCount" label="Updated Item Count" rules={[{ required: true, type: 'number', min: 1 }]}>
                        <InputNumber min={1} style={{ width: '100%' }} />
                      </Form.Item>
                      <Button type="primary" htmlType="submit" loading={updatingOrder}>
                        Update Floor Order
                      </Button>
                    </Form>
                  </Card>
                  <Card title="Latest Workflow Result">
                    {lastOrderResponse ? (
                      <Descriptions bordered size="small" column={1}>
                        <Descriptions.Item label="Context Id">{lastOrderResponse.contextId}</Descriptions.Item>
                        <Descriptions.Item label="Order Id">{lastOrderResponse.orderId}</Descriptions.Item>
                        <Descriptions.Item label="Accepted">{String(lastOrderResponse.accepted)}</Descriptions.Item>
                        <Descriptions.Item label="Status">
                          <Tag color={workflowTagColor(lastOrderResponse.status)}>{lastOrderResponse.status}</Tag>
                        </Descriptions.Item>
                        <Descriptions.Item label="Summary">{lastOrderResponse.summary}</Descriptions.Item>
                        <Descriptions.Item label="Next Step">{orderProgressHint(lastOrderResponse.status)}</Descriptions.Item>
                        <Descriptions.Item label="Processed At">{lastOrderResponse.processedAtUtc}</Descriptions.Item>
                      </Descriptions>
                    ) : (
                      <Empty description="Submit or update an order to inspect the response payload." />
                    )}
                  </Card>
                  <Card title="Recent Workflow Actions">
                    <Table<OrderEvent>
                      pagination={false}
                      rowKey={(record) => `${record.kind}-${record.response.orderId}-${record.response.processedAtUtc}`}
                      dataSource={orderHistory}
                      locale={{ emptyText: 'No recent floor order actions yet.' }}
                      columns={[
                        {
                          title: 'Action',
                          render: (_, record) => <Tag color={record.kind === 'submitted' ? 'green' : 'orange'}>{record.kind}</Tag>
                        },
                        { title: 'Order Id', render: (_, record) => record.response.orderId },
                        {
                          title: 'Status',
                          render: (_, record) => <Tag color={workflowTagColor(record.response.status)}>{record.response.status}</Tag>
                        },
                        { title: 'Summary', render: (_, record) => record.response.summary },
                        { title: 'Processed At', render: (_, record) => record.response.processedAtUtc }
                      ]}
                    />
                  </Card>
                </Space>
              }
            />
            <Route
              path="/session"
              element={
                <Card title="Session Details">
                  <pre>{JSON.stringify(session.profile, null, 2)}</pre>
                </Card>
              }
            />
            <Route path="/" element={<Navigate to="/assignments" replace />} />
            <Route path="*" element={<Navigate to="/assignments" replace />} />
          </Routes>
        </Layout.Content>
      </Layout>
    </Layout>
  );
}

function providerLabel(provider: IdentityProvider): string {
  if (provider === 0 || provider === '0' || provider === 'InternalJwt') {
    return 'Internal JWT';
  }

  if (provider === 1 || provider === '1' || provider === 'AzureAd') {
    return 'Azure AD';
  }

  if (provider === 2 || provider === '2' || provider === 'Google') {
    return 'Google';
  }

  return String(provider);
}

function workflowTagColor(status: string): string {
  switch (status.toLowerCase()) {
    case 'accepted':
      return 'blue';
    case 'preparing':
    case 'cooking':
      return 'gold';
    case 'ready':
    case 'readyforpickup':
      return 'cyan';
    case 'served':
    case 'paid':
      return 'green';
    case 'blocked':
    case 'failed':
    case 'canceled':
      return 'red';
    default:
      return 'default';
  }
}

function orderProgressHint(status: string): string {
  switch (status.toLowerCase()) {
    case 'accepted':
      return 'Kitchen should pick this order up next.';
    case 'preparing':
    case 'cooking':
      return 'Kitchen is actively preparing this order.';
    case 'ready':
    case 'readyforpickup':
      return 'The order is ready for handoff or service.';
    case 'served':
      return 'POS can now treat this check as payable.';
    case 'paid':
      return 'This restaurant check is fully closed.';
    default:
      return 'Track this order across the shared restaurant lifecycle.';
  }
}

export default App;
