# MetaMuLate Implementation Guide

This document provides a comprehensive guide for completing the integration of MetaMuLate into the Orchard Suite OA Panel framework.

## Table of Contents

1. [Project Overview](#project-overview)
2. [Quick Start](#quick-start)
3. [Architecture](#architecture)
4. [Integration Steps](#integration-steps)
5. [Remaining Work](#remaining-work)
6. [Testing Strategy](#testing-strategy)
7. [Deployment](#deployment)

---

## Project Overview

MetaMuLate is a metadata reconciliation tool that:
- Discovers tracks from multiple APIs (Apple, Discogs, MusicBrainz, etc.)
- Presents metadata side-by-side in a matrix view
- Allows users to select "golden" values from any source
- Exports reconciled metadata for bulk processing

### Current State (Updated)

This decomposition has created:
- ✅ TypeScript types for all data structures (DataValue, TrackMetadata, GoldenRecord)
- ✅ Core services (Logger, ProxyService, RateLimiter, ScrapeManager)
- ✅ React components (Header, TrackList, MetadataMatrix, Console, GoldenRecord panel)
- ✅ Custom hooks (useScraping, useLocalStorage, useGoldenRecord)
- ✅ SQL templates for Snowflake queries
- ✅ SPARQL templates for Wikidata queries
- ✅ Documentation (component mapping, GraphQL schema)
- ✅ All API scrapers (Apple, Discogs, MusicBrainz, Genius, Wikidata, Bandcamp)
- ✅ Authority Score utility functions with tests
- ✅ MetadataMatrix with GridTable and category collapse
- ✅ GoldenRecord panel with inline editing
- ✅ Modals (ConnectionsModal, WebScrapeModal)
- ✅ OAPanel shared component wrapper
- ✅ Orchard Light Theme styles with OA token mapping
- ✅ Jest configuration and component tests
- ✅ Vite build configuration

### Remaining Work

- ⏳ Complete GraphQL codegen integration (waiting for backend schema)
- ⏳ Snowflake query hook completion (pending backend availability)
- ⏳ E2E testing with Cypress
- ⏳ Visual regression tests
- ⏳ Production deployment configuration
- ⏳ Feature flag integration for OA rollout

---

## Quick Start

```bash
# Install dependencies
npm install

# Start development server
npm run dev

# Run tests
npm test

# Build for production
npm run build
```

---

## Architecture

### Directory Structure

```
src/
├── components/         # React components
│   ├── Header/
│   ├── TrackList/
│   ├── Matrix/
│   ├── Console/
│   └── Tour/
├── contexts/           # React contexts
│   └── MetamulateContext.tsx
├── hooks/              # Custom React hooks
│   ├── useScraping.ts
│   ├── useLocalStorage.ts
│   └── useGoldenRecord.ts
├── services/           # Business logic services
│   ├── Logger.ts
│   ├── ProxyService.ts
│   ├── RateLimiter.ts
│   ├── ScrapeManager.ts
│   └── ApiClient.ts
├── types/              # TypeScript interfaces
│   ├── DataValue.ts
│   ├── TrackMetadata.ts
│   ├── GoldenRecord.ts
│   └── ...
├── utils/              # Utility functions
│   └── authorityScore/
├── data/               # Static data (SQL templates)
│   └── sql/
├── styles/             # CSS styles
└── App.tsx             # Main application
```

### Data Flow

```
User Input → ArtistSearch
                ↓
        Apple Music API (Discovery)
                ↓
           TrackMetadata[]
                ↓
        ScrapeManager (Enrichment)
                ↓
    Multiple APIs (Discogs, MB, Genius, etc.)
                ↓
           MatrixGrid
                ↓
    User Selection → GoldenRecord
                ↓
           Export/Resolve
```

---

## Integration Steps

### 1. Suite-Components Integration

Replace custom components with `@theorchard/suite-components`:

```tsx
// Before (current)
<button className="px-4 py-2 bg-blue-600">Export</button>

// After (suite-components)
import { Button } from '@theorchard/suite-components';
<Button variant="primary">Export</Button>
```

Key components to replace:
- `Button` → suite `Button`
- `input` → suite `Input`, `SearchInput`
- Custom modals → suite `Modal`
- Custom dropdowns → suite `Dropdown`
- Custom tooltips → suite `Tooltip`

### 2. Apollo Client Integration

Add GraphQL queries/mutations:

```tsx
import { useQuery, useMutation } from '@apollo/client';
import { SNOWFLAKE_LOOKUP } from '@/graphql/queries';

function useSnowflakeLookup(trackName: string, artistName: string) {
  return useQuery(SNOWFLAKE_LOOKUP, {
    variables: { trackName, artistName },
    skip: !trackName || !artistName,
  });
}
```

### 3. OA Panel Wrapper

Wrap the app in OA Panel container:

```tsx
import { OAPanel, OAPanelHeader, OAPanelContent } from '@theorchard/suite-components';

function MetamulateOAPanel() {
  return (
    <OAPanel>
      <OAPanelHeader title="MetaMuLate" />
      <OAPanelContent>
        <App />
      </OAPanelContent>
    </OAPanel>
  );
}
```

### 4. Authentication Integration

Use existing Orchard auth for Snowflake:

```tsx
import { useAuth } from '@theorchard/suite-auth';

function useSnowflakeWithAuth() {
  const { user, getToken } = useAuth();
  
  // Use SSO token for Snowflake queries
  return useSnowflakeLookup({
    context: {
      headers: {
        Authorization: `Bearer ${getToken()}`,
      },
    },
  });
}
```

---

## Remaining Work

### Priority 1: Core Functionality

1. **API Clients** - Port the following from HTML:
   - `services/api/AppleClient.ts`
   - `services/api/DiscogsClient.ts`
   - `services/api/MusicBrainzClient.ts`
   - `services/api/GeniusClient.ts`
   - `services/api/SnowflakeClient.ts`
   - `services/api/WikidataClient.ts`
   - `services/api/BandcampClient.ts`

2. **Matrix Component** - Complete implementation:
   - `components/Matrix/MetadataMatrix.tsx`
   - `components/Matrix/MatrixHeaderRow.tsx`
   - `components/Matrix/MatrixCategory.tsx`
   - `components/Matrix/MatrixRow.tsx`

3. **Golden Record Panel**:
   - `components/GoldenRecord/GoldenRecordPanel.tsx`
   - `components/GoldenRecord/EditableField.tsx`
   - `components/GoldenRecord/PreviewArtwork.tsx`

### Priority 2: Modals

1. `components/Modals/ConnectionsModal.tsx`
2. `components/Modals/WebScrapeModal.tsx`
3. `components/Modals/BandcampUrlModal.tsx`
4. `components/Modals/LyricsModal.tsx`
5. `components/Modals/WikidataEditorModal.tsx`

### Priority 3: Polish

1. Theme system integration
2. Keyboard shortcuts
3. Accessibility (ARIA)
4. Performance optimization
5. Error boundaries

---

## Testing Strategy

### Unit Tests

```typescript
// Example: Authority Score tests
describe('calculateAuthorityScore', () => {
  it('should return 50 for ISRC only', () => {
    const track = createTrack({ isrc: 'USRC1234567' });
    expect(calculateAuthorityScore(track).isrcBonus).toBe(50);
  });
});
```

### Integration Tests

```typescript
// Example: Scrape flow test
describe('ScrapeManager', () => {
  it('should orchestrate concurrent scraping', async () => {
    const results = await ScrapeManager.startScraping(
      mockTrack,
      ['apple', 'discogs'],
      mockScrapers
    );
    expect(results.size).toBe(2);
  });
});
```

### E2E Tests

Use Playwright for full flow testing:

```typescript
test('complete track resolution flow', async ({ page }) => {
  await page.goto('/metamulate');
  await page.fill('[data-testid="search-input"]', 'Daft Punk');
  await page.click('[data-testid="search-button"]');
  await page.waitForSelector('[data-testid="track-item"]');
  // ... continue flow
});
```

---

## Deployment

### Environment Variables

```env
VITE_APPLE_MUSIC_API_KEY=your_key
VITE_DISCOGS_TOKEN=your_token
VITE_GENIUS_TOKEN=your_token
VITE_SNOWFLAKE_PROXY_URL=http://localhost:8081
```

### Build Configuration

The `vite.config.ts` is configured for:
- TypeScript paths (@/ alias)
- React Fast Refresh
- Source maps in development
- Minification in production

### Docker Deployment

```dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "run", "preview"]
```

---

## Support

For questions or issues, contact:
- Technical Lead: [Your Name]
- Slack: #metamulate-dev
- JIRA: METAMULATE project
